pasika 0.10.101 → 0.10.102

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.
@@ -38,8 +38,8 @@ function memberPropertyName(node) {
38
38
  }
39
39
  return void 0;
40
40
  }
41
- function importedContractMember(expression, propertyName5, imports) {
42
- if (expression?.type !== "MemberExpression" || memberPropertyName(expression) !== propertyName5 || expression.object.type !== "Identifier" || !imports.has(expression.object.name)) {
41
+ function importedContractMember(expression, propertyName6, imports) {
42
+ if (expression?.type !== "MemberExpression" || memberPropertyName(expression) !== propertyName6 || expression.object.type !== "Identifier" || !imports.has(expression.object.name)) {
43
43
  return void 0;
44
44
  }
45
45
  return expression.object.name;
@@ -1878,8 +1878,8 @@ function collectSections(node) {
1878
1878
  function collectSteps(content, section) {
1879
1879
  const lists = content.filter((node) => node.type === "list");
1880
1880
  const paragraphs = content.filter((node) => node.type === "paragraph");
1881
- const steps = lists.length > 0 ? lists.flatMap((list) => list.children) : paragraphs.slice(content[0]?.type === "paragraph" ? 1 : 0);
1882
- for (const step of steps) {
1881
+ const steps2 = lists.length > 0 ? lists.flatMap((list) => list.children) : paragraphs.slice(content[0]?.type === "paragraph" ? 1 : 0);
1882
+ for (const step of steps2) {
1883
1883
  section.stepTexts.push(getTextContent(step));
1884
1884
  if (section.stepTexts.length === 1) collectDocLinks(step, section.firstStepLinks);
1885
1885
  }
@@ -2316,11 +2316,11 @@ var guideStepSingleSentenceRule = {
2316
2316
  if (!filename.endsWith("-guide.md")) return;
2317
2317
  if (!listsOnPath.at(-1)?.ordered) return;
2318
2318
  const text = getTextContent(node).trim();
2319
- const sentenceCount = countSentences(text);
2320
- if (sentenceCount > 1) {
2319
+ const sentenceCount2 = countSentences(text);
2320
+ if (sentenceCount2 > 1) {
2321
2321
  context.report({
2322
2322
  node,
2323
- message: `step uses ${String(sentenceCount)} sentences`
2323
+ message: `step uses ${String(sentenceCount2)} sentences`
2324
2324
  });
2325
2325
  }
2326
2326
  }
@@ -2453,7 +2453,7 @@ var overviewRule = {
2453
2453
  }
2454
2454
  }
2455
2455
  if (!titleLine) return;
2456
- let sentenceCount = 0;
2456
+ let sentenceCount2 = 0;
2457
2457
  let found = false;
2458
2458
  for (const child of node.children) {
2459
2459
  if (child.type === "heading" && getLine(child) > titleLine) break;
@@ -2467,11 +2467,11 @@ var overviewRule = {
2467
2467
  message: "overview links another document"
2468
2468
  });
2469
2469
  }
2470
- sentenceCount += countSentences2(text);
2471
- if (sentenceCount > 2) {
2470
+ sentenceCount2 += countSentences2(text);
2471
+ if (sentenceCount2 > 2) {
2472
2472
  context.report({
2473
2473
  node: child,
2474
- message: `overview uses ${String(sentenceCount)} sentences, at most two are allowed`
2474
+ message: `overview uses ${String(sentenceCount2)} sentences, at most two are allowed`
2475
2475
  });
2476
2476
  break;
2477
2477
  }
@@ -2822,6 +2822,43 @@ var rulePairedExamplesRule = {
2822
2822
  message: `Rule level-2 heading must be an Incorrect/Correct example: ${text}`
2823
2823
  });
2824
2824
  }
2825
+ const firstExampleIndex = node.children.findIndex((child) => child.type === "heading" && child.depth === 2);
2826
+ const requirementsIndex = node.children.findIndex(
2827
+ (child, index) => index < firstExampleIndex && child.type === "list" && !child.ordered
2828
+ );
2829
+ if (requirementsIndex !== -1) {
2830
+ const requirements = node.children[requirementsIndex];
2831
+ if (requirements?.type === "list" && requirements.spread) {
2832
+ context.report({
2833
+ node: requirements,
2834
+ message: "Rule requirement bullets must form one uninterrupted list without blank lines"
2835
+ });
2836
+ }
2837
+ for (const child of node.children.slice(requirementsIndex + 1, firstExampleIndex)) {
2838
+ context.report({
2839
+ node: child,
2840
+ message: "Rule requirements must be followed directly by the first Incorrect/Correct example"
2841
+ });
2842
+ }
2843
+ }
2844
+ let inExample = false;
2845
+ let afterWhy = false;
2846
+ for (const child of node.children) {
2847
+ if (child.type === "heading" && child.depth === 2) {
2848
+ inExample = true;
2849
+ afterWhy = false;
2850
+ continue;
2851
+ }
2852
+ if (!inExample) continue;
2853
+ if (afterWhy) {
2854
+ context.report({
2855
+ node: child,
2856
+ message: "A Why explanation must be the final block of its example"
2857
+ });
2858
+ } else if (child.type === "paragraph" && getTextContent(child).trim().startsWith("Why:")) {
2859
+ afterWhy = true;
2860
+ }
2861
+ }
2825
2862
  const incorrect = exampleHeadings.filter((h) => h.text.startsWith("Incorrect"));
2826
2863
  const correct = exampleHeadings.filter((h) => h.text.startsWith("Correct"));
2827
2864
  if (incorrect.length === 0 || incorrect.length !== correct.length) {
@@ -2922,6 +2959,38 @@ var titleMatchesFileNameRule = {
2922
2959
  }
2923
2960
  };
2924
2961
 
2962
+ // eslint/rules/documentation/why-sentence-limit.ts
2963
+ var MAX_SENTENCES = 2;
2964
+ function sentenceCount(text) {
2965
+ const normalized = text.replace(/\b(?:e\.g|i\.e)\./gi, (match) => match.replaceAll(".", ""));
2966
+ return normalized.split(/[.!?]+["'’”\])]*(?:\s+|$)/).filter((part) => part.trim().length > 0).length;
2967
+ }
2968
+ var whySentenceLimitRule = {
2969
+ meta: {
2970
+ type: "problem",
2971
+ docs: {
2972
+ description: "Why explanations in Rules may use at most two sentences.",
2973
+ recommended: true
2974
+ }
2975
+ },
2976
+ create(context) {
2977
+ return {
2978
+ paragraph(node) {
2979
+ if (!getFilename(context).endsWith("-rule.md")) return;
2980
+ const text = node.children.map((child) => child.type === "inlineCode" ? "code" : getTextContent(child)).join("").trim();
2981
+ if (!text.startsWith("Why:")) return;
2982
+ const count = sentenceCount(text.slice("Why:".length).trim());
2983
+ if (count > MAX_SENTENCES) {
2984
+ context.report({
2985
+ node,
2986
+ message: `Why explanation has ${String(count)} sentences; maximum is ${String(MAX_SENTENCES)}.`
2987
+ });
2988
+ }
2989
+ }
2990
+ };
2991
+ }
2992
+ };
2993
+
2925
2994
  // eslint/rules/documentation/index.ts
2926
2995
  var documentationRules = {
2927
2996
  "doc-kind-suffix": docKindSuffixRule,
@@ -2932,6 +3001,7 @@ var documentationRules = {
2932
3001
  "guide-states-no-requirement": guideStatesNoRequirementRule,
2933
3002
  "requirement-present": requirementPresentRule,
2934
3003
  "rule-paired-examples": rulePairedExamplesRule,
3004
+ "why-sentence-limit": whySentenceLimitRule,
2935
3005
  "example-heading-description": exampleHeadingDescriptionRule,
2936
3006
  "policy-no-examples": policyNoExamplesRule,
2937
3007
  "no-cross-document-link": noCrossDocumentLinkRule,
@@ -3850,10 +3920,9 @@ var huskyHookRule = {
3850
3920
  requireNamedScript("test:unit:coverage");
3851
3921
  const autoStageAll = /^\s*git\s+add\s+(?:--\s+)?(?:-A|--all|-u|\.)(?:\s*(?:#.*)?)?$/m.test(commands);
3852
3922
  const coverageIndex = commands.indexOf("npm run test:unit:coverage");
3853
- const coverageGuard = /if\s+!\s+git\s+diff\s+--quiet\s+--\s+vitest\.config\.ts\s*;\s*then[\s\S]*?\bexit\s+1\b[\s\S]*?\bfi\b/.exec(
3854
- commands
3855
- );
3856
- if (coverageIndex >= 0 && (!coverageGuard || coverageGuard.index <= coverageIndex)) {
3923
+ const coverageGuards = /if\s+!\s+git\s+diff\s+--quiet\s+--\s+vitest\.config\.ts\s*;\s*then[\s\S]*?\bexit\s+1\b[\s\S]*?\bfi\b|git\s+diff\s+--exit-code\s+--\s+vitest\.config\.ts\s*\|\|\s*exit\s+1\b/g;
3924
+ const hasCoverageGuard = [...commands.matchAll(coverageGuards)].some((match) => match.index > coverageIndex);
3925
+ if (coverageIndex >= 0 && !hasCoverageGuard) {
3857
3926
  context.report({
3858
3927
  node,
3859
3928
  message: ".husky/pre-commit must reject unstaged vitest.config.ts changes after coverage."
@@ -3872,25 +3941,11 @@ var huskyHookRule = {
3872
3941
  message: ".husky/pre-commit must run npx vulyk sync and npx vulyk agents before lint-staged."
3873
3942
  });
3874
3943
  }
3875
- const vulykGuard = /if\s+!\s+git\s+diff\s+--quiet\s+--[\s\S]*?git\s+ls-files\s+--others\s+--exclude-standard\s+--[\s\S]*?\bexit\s+1\b[\s\S]*?\bfi\b/.exec(
3876
- commands
3877
- );
3878
- const tracked = /git diff --quiet -- (?<paths>[^\r\n]*)/.exec(vulykGuard?.[0] ?? "")?.groups?.paths;
3879
- const untracked = /git ls-files --others --exclude-standard -- (?<paths>[^\r\n)]*)/.exec(
3880
- vulykGuard?.[0] ?? ""
3881
- )?.groups?.paths;
3882
- const outputPaths = ["AGENTS.md", "CLAUDE.md", "docs/managed"];
3883
- const hasPaths = outputPaths.every((output) => tracked?.includes(output) && untracked?.includes(output));
3884
- if (!hasPaths || !vulykGuard || vulykGuard.index <= agentsIndex || vulykGuard.index >= stagedIndex) {
3885
- context.report({
3886
- node,
3887
- message: ".husky/pre-commit must reject unstaged and untracked Vulyk-generated files before lint-staged."
3888
- });
3889
- }
3890
- if (autoStageAll || /\bgit\s+add\s+(?:-A\s+|--all\s+|--\s+)?(?:AGENTS\.md|CLAUDE\.md|docs\/managed)\b/.test(commands)) {
3944
+ const stageIndex = commands.search(/\bnpx\s+vulyk\s+stage\b/);
3945
+ if (stageIndex <= agentsIndex || stageIndex >= stagedIndex) {
3891
3946
  context.report({
3892
3947
  node,
3893
- message: ".husky/pre-commit must not auto-stage Vulyk-generated files."
3948
+ message: ".husky/pre-commit must run npx vulyk stage after agents and before lint-staged."
3894
3949
  });
3895
3950
  }
3896
3951
  }
@@ -4489,7 +4544,7 @@ var localeDottedPathRule = {
4489
4544
  schema: [],
4490
4545
  type: "problem",
4491
4546
  docs: {
4492
- description: "Require reading namespaced locales through their full dotted path."
4547
+ description: "Require direct global and feature locale access without destructuring."
4493
4548
  }
4494
4549
  },
4495
4550
  create(context) {
@@ -4510,7 +4565,7 @@ var localeDottedPathRule = {
4510
4565
  if (valueName) {
4511
4566
  context.report({
4512
4567
  node,
4513
- message: `Destructuring locales.${valueName} loses the namespace; read through the full dotted path instead.`
4568
+ message: `Destructuring locales.${valueName} hides its key path; access locales directly instead.`
4514
4569
  });
4515
4570
  }
4516
4571
  }
@@ -4569,10 +4624,15 @@ var ROLE_POSTFIXES = /* @__PURE__ */ new Set([
4569
4624
  ]);
4570
4625
  var CAMEL_CASE = /^[a-z][a-zA-Z0-9]*$/;
4571
4626
  var ENGLISH = /^[A-Za-z0-9_]*$/;
4572
- function isLocalesFile(filename) {
4627
+ function dictionaryName(filename) {
4573
4628
  const segments = path35.resolve(filename).split(path35.sep);
4574
4629
  const srcIdx = segments.lastIndexOf("src");
4575
- return srcIdx !== -1 && segments[srcIdx + 1] === "locales";
4630
+ if (srcIdx < 0 || segments[srcIdx + 1] !== "locales") return void 0;
4631
+ const remaining = segments.slice(srcIdx + 2);
4632
+ if (remaining.length === 1 && remaining[0] !== "index.ts" && /^[a-z][a-z0-9]*(?:-[a-z0-9]+)*\.ts$/.test(remaining[0] ?? "")) {
4633
+ return remaining[0]?.slice(0, -3).replace(/-[a-z]/g, (match) => match.slice(1).toUpperCase());
4634
+ }
4635
+ return void 0;
4576
4636
  }
4577
4637
  function keyName(key) {
4578
4638
  if (key.type === "Identifier") return key.name;
@@ -4629,31 +4689,28 @@ var localeKeyShapeRule = {
4629
4689
  }
4630
4690
  },
4631
4691
  create(context) {
4632
- if (!isLocalesFile(context.filename)) return {};
4633
- function visitObject(node, namespace) {
4692
+ const dictionary = dictionaryName(context.filename) ?? "";
4693
+ if (!dictionary) return {};
4694
+ function visitObject(node) {
4634
4695
  for (const property of node.properties) {
4635
4696
  if (property.type !== "Property") continue;
4636
4697
  const name = keyName(property.key);
4637
4698
  if (name === void 0) continue;
4638
4699
  const nested = localeObject(property.value);
4639
4700
  if (nested) {
4640
- if (namespace !== void 0) {
4641
- reportFor(
4642
- context,
4643
- property,
4644
- `Locale "${namespace}.${name}" must not be a nested object. Keep string keys directly inside the "${namespace}" feature namespace. See docs/next-codebase-guide/rules/locales-rule.md`
4645
- );
4646
- } else {
4647
- visitObject(nested, name);
4648
- }
4649
- } else if (property.value.type === "Literal" && typeof property.value.value === "string") {
4701
+ reportFor(
4702
+ context,
4703
+ property,
4704
+ `Locale "${dictionary}.${name}" must not be a nested object. Keep string keys directly inside the "${dictionary}" namespace. See docs/next-codebase-guide/rules/locales-rule.md`
4705
+ );
4706
+ } else if (property.value.type === "Literal" && typeof property.value.value === "string" || property.value.type === "TemplateLiteral" && property.value.expressions.length === 0) {
4650
4707
  checkKey(context, property, name);
4651
4708
  }
4652
4709
  }
4653
4710
  }
4654
4711
  return {
4655
4712
  VariableDeclarator(node) {
4656
- if (node.id.type !== "Identifier" || node.id.name !== "locales") return;
4713
+ if (node.id.type !== "Identifier" || node.id.name !== dictionary) return;
4657
4714
  const root = localeObject(node.init);
4658
4715
  if (!root) return;
4659
4716
  visitObject(root);
@@ -4663,135 +4720,307 @@ var localeKeyShapeRule = {
4663
4720
  };
4664
4721
 
4665
4722
  // eslint/rules/locale-placement.ts
4666
- import { readFileSync as readFileSync7 } from "fs";
4723
+ import { readFileSync as readFileSync8 } from "fs";
4724
+ import path37 from "path";
4725
+ import ts7 from "typescript";
4726
+
4727
+ // eslint/rules/locale-definitions.ts
4728
+ import { existsSync as existsSync5, readFileSync as readFileSync7, readdirSync as readdirSync3 } from "fs";
4667
4729
  import path36 from "path";
4668
4730
  import ts6 from "typescript";
4669
- var LOCALE_ACCESS = /\blocales\.(?<key>[A-Za-z_$][\w$]*)/g;
4670
4731
  var camelCase = (name) => name.replace(/-[a-z]/g, (match) => match.slice(1).toUpperCase());
4671
- var FORCED_TOP_LEVEL = /* @__PURE__ */ new Set(["app", "shared", "compositions", "config"]);
4672
- function forcesTopLevel(segments) {
4673
- return FORCED_TOP_LEVEL.has(segments[0] ?? "") || SUPPORT_FOLDERS.has(segments[0] ?? "");
4732
+ function unwrap(expression) {
4733
+ if (ts6.isAsExpression(expression) || ts6.isSatisfiesExpression(expression) || ts6.isParenthesizedExpression(expression)) {
4734
+ return unwrap(expression.expression);
4735
+ }
4736
+ return expression;
4674
4737
  }
4675
- function localePlacement(text) {
4676
- const sourceFile = ts6.createSourceFile("locales.ts", text, ts6.ScriptTarget.Latest, true, ts6.ScriptKind.TS);
4677
- for (const statement of sourceFile.statements) {
4738
+ function exportedDictionary(source, name) {
4739
+ for (const statement of source.statements) {
4678
4740
  if (!ts6.isVariableStatement(statement)) continue;
4679
- const isExported3 = (ts6.getModifiers(statement) ?? []).some(
4741
+ const exported = (ts6.getModifiers(statement) ?? []).some(
4680
4742
  (modifier) => modifier.kind === ts6.SyntaxKind.ExportKeyword
4681
4743
  );
4682
- if (!isExported3) continue;
4744
+ if (!exported || !(statement.declarationList.flags & ts6.NodeFlags.Const)) continue;
4745
+ if (statement.declarationList.declarations.length !== 1) continue;
4683
4746
  for (const declaration of statement.declarationList.declarations) {
4684
- if (!ts6.isIdentifier(declaration.name) || declaration.name.text !== "locales") continue;
4685
- if (!declaration.initializer || !ts6.isObjectLiteralExpression(declaration.initializer)) continue;
4686
- const placement = /* @__PURE__ */ new Map();
4687
- for (const property of declaration.initializer.properties) {
4688
- if (!ts6.isPropertyAssignment(property)) continue;
4689
- let name;
4690
- if (ts6.isIdentifier(property.name)) name = property.name.text;
4691
- else if (ts6.isStringLiteral(property.name)) name = property.name.text;
4692
- if (name === void 0) continue;
4693
- const line = sourceFile.getLineAndCharacterOfPosition(property.getStart(sourceFile)).line + 1;
4694
- placement.set(name, {
4695
- kind: ts6.isObjectLiteralExpression(property.initializer) ? "nested" : "top",
4696
- line
4697
- });
4747
+ if (ts6.isIdentifier(declaration.name) && declaration.name.text === name && declaration.initializer) {
4748
+ const value = unwrap(declaration.initializer);
4749
+ if (ts6.isObjectLiteralExpression(value)) return value;
4698
4750
  }
4699
- return placement;
4700
4751
  }
4701
4752
  }
4702
4753
  return void 0;
4703
4754
  }
4755
+ function propertyName2(property) {
4756
+ if (ts6.isIdentifier(property) || ts6.isStringLiteral(property)) return property.text;
4757
+ return void 0;
4758
+ }
4759
+ function expectedPath(localesRoot, namespace) {
4760
+ const kebab = namespace.replace(/[A-Z]/g, (letter) => `-${letter.toLowerCase()}`);
4761
+ return path36.join(localesRoot, `${kebab}.ts`);
4762
+ }
4763
+ function validateDictionary(file, namespace, errors) {
4764
+ const values = /* @__PURE__ */ new Map();
4765
+ if (!existsSync5(file)) {
4766
+ errors.push(`Missing locale dictionary for ${namespace}.`);
4767
+ return values;
4768
+ }
4769
+ const source = ts6.createSourceFile(file, readFileSync7(file, "utf8"), ts6.ScriptTarget.Latest, true, ts6.ScriptKind.TS);
4770
+ const dictionary = exportedDictionary(source, namespace);
4771
+ if (!dictionary || source.statements.length !== 1) {
4772
+ errors.push(`Locale module ${file} must contain only an exported const ${namespace} string dictionary.`);
4773
+ return values;
4774
+ }
4775
+ for (const property of dictionary.properties) {
4776
+ if (!ts6.isPropertyAssignment(property)) {
4777
+ errors.push(`Locale dictionary ${namespace} must use explicit string properties.`);
4778
+ continue;
4779
+ }
4780
+ const name = propertyName2(property.name);
4781
+ const value = unwrap(property.initializer);
4782
+ if (!name || !/^[a-z][a-zA-Z0-9]*$/.test(name) || values.has(name) || !ts6.isStringLiteral(value) && !ts6.isNoSubstitutionTemplateLiteral(value)) {
4783
+ errors.push(`Locale dictionary ${namespace} has an invalid, duplicate, or non-string key.`);
4784
+ continue;
4785
+ }
4786
+ values.set(name, value.text);
4787
+ }
4788
+ return values;
4789
+ }
4790
+ function readLocaleDefinitions(indexFile) {
4791
+ const definitions = /* @__PURE__ */ new Map();
4792
+ const errors = [];
4793
+ const root = path36.dirname(indexFile);
4794
+ const source = ts6.createSourceFile(
4795
+ indexFile,
4796
+ readFileSync7(indexFile, "utf8"),
4797
+ ts6.ScriptTarget.Latest,
4798
+ true,
4799
+ ts6.ScriptKind.TS
4800
+ );
4801
+ const imports = /* @__PURE__ */ new Map();
4802
+ for (const statement of source.statements) {
4803
+ if (ts6.isImportDeclaration(statement) && ts6.isStringLiteral(statement.moduleSpecifier)) {
4804
+ const named = statement.importClause?.namedBindings;
4805
+ if (!named || !ts6.isNamedImports(named)) {
4806
+ errors.push("Locale index imports must use named imports.");
4807
+ continue;
4808
+ }
4809
+ for (const element of named.elements) {
4810
+ if (element.propertyName || imports.has(element.name.text)) {
4811
+ errors.push("Locale index must import dictionaries by their original names without aliases.");
4812
+ }
4813
+ imports.set(element.name.text, statement.moduleSpecifier.text);
4814
+ }
4815
+ } else if (!ts6.isVariableStatement(statement)) {
4816
+ errors.push("Locale index may contain only imports and the exported locales dictionary.");
4817
+ }
4818
+ }
4819
+ const dictionary = exportedDictionary(source, "locales");
4820
+ if (!dictionary || source.statements.filter(ts6.isVariableStatement).length !== 1) {
4821
+ errors.push("Locale index must export a single const locales dictionary.");
4822
+ return { definitions, errors };
4823
+ }
4824
+ for (const property of dictionary.properties) {
4825
+ let name;
4826
+ let value;
4827
+ if (ts6.isSpreadAssignment(property)) {
4828
+ if (!ts6.isIdentifier(property.expression) || property.expression.text !== "global") {
4829
+ errors.push("Locale index may only spread the global dictionary.");
4830
+ continue;
4831
+ }
4832
+ name = "global";
4833
+ value = "global";
4834
+ } else if (ts6.isShorthandPropertyAssignment(property)) {
4835
+ name = property.name.text;
4836
+ value = name;
4837
+ } else if (ts6.isPropertyAssignment(property)) {
4838
+ name = propertyName2(property.name);
4839
+ const initial = unwrap(property.initializer);
4840
+ if (ts6.isIdentifier(initial)) value = initial.text;
4841
+ }
4842
+ if (!name || !value || name !== value || definitions.has(name) || !/^[a-z][a-zA-Z0-9]*$/.test(name)) {
4843
+ errors.push("Locale index must expose feature dictionaries by name and spread only global, without aliases.");
4844
+ continue;
4845
+ }
4846
+ if (name === "global" && !ts6.isSpreadAssignment(property)) {
4847
+ errors.push("Locale index must spread global keys into the top level.");
4848
+ continue;
4849
+ }
4850
+ if (name === "shared" || name === "compositions") {
4851
+ errors.push(`Locale namespace ${name} must not be used as a catch-all dictionary.`);
4852
+ continue;
4853
+ }
4854
+ const expected = expectedPath(root, name);
4855
+ const actualImport = imports.get(name);
4856
+ if (!actualImport || path36.resolve(root, actualImport + (path36.extname(actualImport) ? "" : ".ts")) !== expected) {
4857
+ errors.push(`Locale namespace ${name} must import its dictionary from ${path36.relative(root, expected)}.`);
4858
+ continue;
4859
+ }
4860
+ const values = validateDictionary(expected, name, errors);
4861
+ definitions.set(name, { namespace: name, file: expected, keys: new Set(values.keys()), values });
4862
+ }
4863
+ if (!definitions.has("global")) {
4864
+ errors.push("Locale index must spread the global dictionary.");
4865
+ }
4866
+ for (const imported of imports.keys()) {
4867
+ if (!definitions.has(imported)) {
4868
+ errors.push(`Imported locale dictionary ${imported} is not exposed in locales.`);
4869
+ }
4870
+ }
4871
+ for (const entry of readdirSync3(root, { withFileTypes: true })) {
4872
+ if (entry.isDirectory()) {
4873
+ errors.push(
4874
+ `Locale dictionaries must live directly in src/locales/; nested folder ${entry.name} is not allowed.`
4875
+ );
4876
+ } else if (entry.isFile() && entry.name.endsWith(".ts") && entry.name !== "index.ts" && !entry.name.endsWith(".test.ts") && !entry.name.endsWith(".d.ts")) {
4877
+ const name = camelCase(entry.name.slice(0, -3));
4878
+ if (!definitions.has(name) && !imports.has(name)) {
4879
+ errors.push(`Locale module ${entry.name} is not exposed in locales.`);
4880
+ }
4881
+ }
4882
+ }
4883
+ const global = definitions.get("global");
4884
+ if (global) {
4885
+ for (const key of global.keys) {
4886
+ if (definitions.has(key)) {
4887
+ errors.push(`Global locale key ${key} conflicts with a feature namespace.`);
4888
+ }
4889
+ }
4890
+ }
4891
+ return { definitions, errors };
4892
+ }
4893
+
4894
+ // eslint/rules/locale-placement.ts
4895
+ var DOC4 = "See docs/next-codebase-guide/rules/locales-rule.md";
4896
+ function localeAccesses(file) {
4897
+ const contents = readFileSync8(file, "utf8");
4898
+ const kind = /\.[jt]sx$/.test(file) ? ts7.ScriptKind.TSX : ts7.ScriptKind.TS;
4899
+ const source = ts7.createSourceFile(file, contents, ts7.ScriptTarget.Latest, true, kind);
4900
+ const accesses = [];
4901
+ const visit = (node) => {
4902
+ if (ts7.isPropertyAccessExpression(node)) {
4903
+ const receiver = node.expression;
4904
+ if (ts7.isPropertyAccessExpression(receiver) && ts7.isIdentifier(receiver.expression) && receiver.expression.text === "locales") {
4905
+ accesses.push({ namespace: receiver.name.text, key: node.name.text });
4906
+ } else if (ts7.isIdentifier(receiver) && receiver.text === "locales" && !(ts7.isPropertyAccessExpression(node.parent) && node.parent.expression === node)) {
4907
+ accesses.push({ namespace: node.name.text });
4908
+ }
4909
+ }
4910
+ ts7.forEachChild(node, visit);
4911
+ };
4912
+ visit(source);
4913
+ return accesses;
4914
+ }
4704
4915
  var localePlacementRule = {
4705
4916
  meta: {
4706
4917
  schema: [],
4707
4918
  type: "problem",
4708
4919
  docs: {
4709
- description: "Require shared locales at the top level and single-feature locales in a namespaced object."
4920
+ description: "Enforce locale placement from consumer folders, with cross-scope strings in global."
4710
4921
  }
4711
4922
  },
4712
4923
  create(context) {
4713
4924
  const sourceRoot = sourceRootOf(context);
4714
- const file = path36.resolve(context.filename);
4925
+ const file = path37.resolve(context.filename);
4715
4926
  const segments = segmentsOf(file, sourceRoot);
4716
4927
  if (segments.length === 0) return {};
4717
4928
  const index = getProjectIndex(sourceRoot);
4718
4929
  if (!index) return {};
4719
4930
  const localesFile = [...index.modules.keys()].find((candidate) => {
4720
- const candidateSegments = segmentsOf(candidate, sourceRoot);
4721
- return candidateSegments.length === 2 && candidateSegments[0] === "locales" && candidateSegments[1]?.startsWith("index.");
4931
+ const parts = segmentsOf(candidate, sourceRoot);
4932
+ return parts.length === 2 && parts[0] === "locales" && parts[1] === "index.ts";
4722
4933
  });
4723
4934
  if (!localesFile || file !== localesFile) return {};
4724
- const placement = localePlacement(readFileSync7(localesFile, "utf8"));
4725
- if (!placement) return {};
4726
- const keyReaders = /* @__PURE__ */ new Map();
4727
- const keyFeatures = /* @__PURE__ */ new Map();
4728
- const keyForcedTopLevel = /* @__PURE__ */ new Set();
4935
+ const { definitions, errors } = readLocaleDefinitions(localesFile);
4936
+ const findings = [...errors];
4937
+ const globalKeys = definitions.get("global")?.keys;
4938
+ const consumers = /* @__PURE__ */ new Map();
4729
4939
  for (const [candidateFile, module] of index.modules) {
4730
4940
  if (candidateFile === localesFile) continue;
4941
+ const candidateSegments = segmentsOf(candidateFile, sourceRoot);
4942
+ if (candidateSegments[0] !== "locales") {
4943
+ const bypassesIndex = module.imports.some((moduleImport) => {
4944
+ const resolved = resolveSpecifier(candidateFile, moduleImport.specifier, sourceRoot);
4945
+ if (!resolved) return false;
4946
+ const target = segmentsOf(resolved, sourceRoot);
4947
+ return target[0] === "locales" && target.length > 1 && target[1] !== "index.ts";
4948
+ });
4949
+ if (bypassesIndex) findings.push(`Locale dictionaries must be imported through src/locales/index.ts. ${DOC4}`);
4950
+ }
4731
4951
  const importsLocales = module.imports.some(
4732
4952
  (moduleImport) => resolveSpecifier(candidateFile, moduleImport.specifier, sourceRoot) === localesFile
4733
4953
  );
4734
4954
  if (!importsLocales) continue;
4735
- const candidateSegments = segmentsOf(candidateFile, sourceRoot);
4736
- for (const match of readFileSync7(candidateFile, "utf8").matchAll(LOCALE_ACCESS)) {
4737
- const key = match.groups?.key;
4738
- if (key === void 0) continue;
4739
- const readers = keyReaders.get(key) ?? /* @__PURE__ */ new Set();
4740
- readers.add(candidateFile);
4741
- keyReaders.set(key, readers);
4742
- if (candidateSegments[0] === "features" && candidateSegments.length >= 2) {
4743
- const features = keyFeatures.get(key) ?? /* @__PURE__ */ new Set();
4744
- features.add(candidateSegments[1] ?? "");
4745
- keyFeatures.set(key, features);
4746
- } else if (forcesTopLevel(candidateSegments)) {
4747
- keyForcedTopLevel.add(key);
4955
+ for (const { namespace, key } of localeAccesses(candidateFile)) {
4956
+ if (key) {
4957
+ if (!definitions.get(namespace)?.keys.has(key) || namespace === "global") {
4958
+ findings.push(`Locale locales.${namespace}.${key} is not defined in a feature dictionary. ${DOC4}`);
4959
+ }
4960
+ } else if (definitions.has(namespace)) {
4961
+ findings.push(`Locale access locales.${namespace} must include a feature key. ${DOC4}`);
4962
+ } else if (!globalKeys?.has(namespace)) {
4963
+ findings.push(`Locale locales.${namespace} is not defined in the global dictionary. ${DOC4}`);
4964
+ }
4965
+ const access = key ? `${namespace}.${key}` : `global.${namespace}`;
4966
+ const used = consumers.get(access) ?? /* @__PURE__ */ new Set();
4967
+ used.add(candidateFile);
4968
+ consumers.set(access, used);
4969
+ }
4970
+ }
4971
+ for (const [namespace, definition] of definitions) {
4972
+ const folder = namespace.replace(/[A-Z]/g, (letter) => `-${letter.toLowerCase()}`);
4973
+ for (const key of definition.keys) {
4974
+ const used = [...consumers.get(`${namespace}.${key}`) ?? []];
4975
+ if (used.length === 0) continue;
4976
+ const featureOf2 = (candidate) => {
4977
+ const parts = segmentsOf(candidate, sourceRoot);
4978
+ return parts[0] === "features" ? parts[1] : void 0;
4979
+ };
4980
+ if (namespace === "global") {
4981
+ const features = new Set(used.map(featureOf2));
4982
+ const feature = [...features][0];
4983
+ if (features.size === 1 && feature !== void 0) {
4984
+ findings.push(
4985
+ `Locale locales.${key} is consumed only by src/features/${feature}/; move it into that feature dictionary. ${DOC4}`
4986
+ );
4987
+ }
4988
+ } else if (used.some((candidate) => featureOf2(candidate) !== folder)) {
4989
+ findings.push(
4990
+ `Locale locales.${namespace}.${key} is used outside src/features/${folder}/; move it into global. ${DOC4}`
4991
+ );
4748
4992
  }
4749
4993
  }
4750
4994
  }
4751
- const findings = [];
4752
- for (const [key, readers] of keyReaders) {
4753
- const features = keyFeatures.get(key) ?? /* @__PURE__ */ new Set();
4754
- const shared = features.size > 1 || keyForcedTopLevel.has(key);
4755
- const current = placement.get(key);
4756
- if (shared) {
4757
- if (current?.kind === "nested") {
4758
- findings.push({
4759
- line: current.line,
4760
- message: `Locale "${key}" is read by ${describeConsumers([...readers], sourceRoot)} and must live at the top level of locales. See docs/next-codebase-guide/rules/locales-rule.md`
4761
- });
4762
- }
4763
- continue;
4995
+ const translations = /* @__PURE__ */ new Map();
4996
+ for (const [namespace, definition] of definitions) {
4997
+ for (const [key, value] of definition.values) {
4998
+ const entries = translations.get(value) ?? /* @__PURE__ */ new Set();
4999
+ entries.add(`${namespace}.${key}`);
5000
+ translations.set(value, entries);
4764
5001
  }
4765
- if (features.size !== 1) continue;
4766
- const featureName = [...features][0] ?? "";
4767
- const expected = camelCase(featureName);
4768
- if (current?.kind === "top") {
4769
- findings.push({
4770
- line: current.line,
4771
- message: `Locale "${key}" is read only by the ${featureName} feature; it must live in an object named "${expected}". See docs/next-codebase-guide/rules/locales-rule.md`
4772
- });
4773
- } else if (current?.kind === "nested" && key !== expected) {
4774
- findings.push({
4775
- line: current.line,
4776
- message: `Locale "${key}" is read only by the ${featureName} feature; it must live in an object named "${expected}", not "${key}". See docs/next-codebase-guide/rules/locales-rule.md`
4777
- });
5002
+ }
5003
+ for (const [value, entries] of translations) {
5004
+ const namespaces = new Set([...entries].map((entry) => entry.split(".")[0]));
5005
+ if (namespaces.size > 1) {
5006
+ findings.push(
5007
+ `Locale text ${JSON.stringify(value)} is duplicated across dictionaries (${[...entries].join(", ")}); reuse one global key. ${DOC4}`
5008
+ );
4778
5009
  }
4779
5010
  }
4780
5011
  if (findings.length === 0) return {};
4781
5012
  return {
4782
5013
  Program(node) {
4783
- for (const finding of findings) {
4784
- context.report({ node, loc: { line: finding.line, column: 0 }, message: finding.message });
4785
- }
5014
+ for (const message of findings) context.report({ node, message });
4786
5015
  }
4787
5016
  };
4788
5017
  }
4789
5018
  };
4790
5019
 
4791
5020
  // eslint/rules/locales-location.ts
4792
- import path37 from "path";
4793
- function isLocalesFile2(filename) {
4794
- const segments = path37.resolve(filename).split(path37.sep);
5021
+ import path38 from "path";
5022
+ function isLocalesFile(filename) {
5023
+ const segments = path38.resolve(filename).split(path38.sep);
4795
5024
  const srcIdx = segments.lastIndexOf("src");
4796
5025
  return srcIdx !== -1 && segments[srcIdx + 1] === "locales";
4797
5026
  }
@@ -4869,9 +5098,9 @@ var localesLocationRule = {
4869
5098
  }
4870
5099
  },
4871
5100
  create(context) {
4872
- if (isLocalesFile2(context.filename) || isTestFile(context.filename)) return {};
5101
+ if (isLocalesFile(context.filename) || isTestFile(context.filename)) return {};
4873
5102
  const filename = context.filename;
4874
- const segments = path37.resolve(filename).split(path37.sep);
5103
+ const segments = path38.resolve(filename).split(path38.sep);
4875
5104
  const srcIdx = segments.lastIndexOf("src");
4876
5105
  if (srcIdx === -1) return {};
4877
5106
  const folder = segments[srcIdx + 1];
@@ -4956,7 +5185,7 @@ var localesLocationRule = {
4956
5185
  };
4957
5186
 
4958
5187
  // eslint/rules/named-exports.ts
4959
- import path38 from "path";
5188
+ import path39 from "path";
4960
5189
  var FRAMEWORK_DEFAULT_EXPORT_FILES = /* @__PURE__ */ new Set([
4961
5190
  // App Router routing files
4962
5191
  "default",
@@ -4978,9 +5207,9 @@ var FRAMEWORK_DEFAULT_EXPORT_FILES = /* @__PURE__ */ new Set([
4978
5207
  "twitter-image"
4979
5208
  ]);
4980
5209
  function isFrameworkDefaultExportFile(filename) {
4981
- const normalized = filename.replaceAll(path38.sep, "/");
5210
+ const normalized = filename.replaceAll(path39.sep, "/");
4982
5211
  if (!normalized.includes("/src/app/")) return false;
4983
- const basename = path38.basename(filename, path38.extname(filename));
5212
+ const basename = path39.basename(filename, path39.extname(filename));
4984
5213
  return FRAMEWORK_DEFAULT_EXPORT_FILES.has(basename);
4985
5214
  }
4986
5215
  var namedExportsRule = {
@@ -5148,12 +5377,12 @@ var noArbitraryTailwindRule = {
5148
5377
  };
5149
5378
 
5150
5379
  // eslint/rules/no-inline-runtime-literal.ts
5151
- import path40 from "path";
5380
+ import path41 from "path";
5152
5381
 
5153
5382
  // eslint/project/semantic-literals.ts
5154
- import { readFileSync as readFileSync8 } from "fs";
5155
- import path39 from "path";
5156
- import ts7 from "typescript";
5383
+ import { readFileSync as readFileSync9 } from "fs";
5384
+ import path40 from "path";
5385
+ import ts8 from "typescript";
5157
5386
  var excludedProperties = /* @__PURE__ */ new Set([
5158
5387
  "label",
5159
5388
  "title",
@@ -5191,33 +5420,33 @@ var columnMethods = /* @__PURE__ */ new Set([
5191
5420
  var eventMethods = /* @__PURE__ */ new Set(["emit", "on", "off", "once", "addListener", "removeListener"]);
5192
5421
  var ignoredNumbers = /* @__PURE__ */ new Set([-1, 0, 1]);
5193
5422
  function isProductionSource(file, root) {
5194
- const parts = path39.relative(root, file).split(path39.sep);
5195
- return !(/\.(?:test|spec|mock)\.[^.]+$/.test(path39.basename(file)) || parts.some((part) => part === "__tests__" || part === "__mocks__" || part === "mocks"));
5423
+ const parts = path40.relative(root, file).split(path40.sep);
5424
+ return !(/\.(?:test|spec|mock)\.[^.]+$/.test(path40.basename(file)) || parts.some((part) => part === "__tests__" || part === "__mocks__" || part === "mocks"));
5196
5425
  }
5197
5426
  function featureOf(file, root) {
5198
- const parts = path39.relative(root, file).split(path39.sep);
5427
+ const parts = path40.relative(root, file).split(path40.sep);
5199
5428
  if (parts[0] === "features" && parts[1]) return `feature:${parts[1]}`;
5200
5429
  return `layer:${parts[0] ?? "src"}`;
5201
5430
  }
5202
5431
  function nameOf(property) {
5203
- if (ts7.isIdentifier(property) || ts7.isStringLiteral(property)) return property.text;
5432
+ if (ts8.isIdentifier(property) || ts8.isStringLiteral(property)) return property.text;
5204
5433
  return void 0;
5205
5434
  }
5206
5435
  function literalOf(node) {
5207
- if (ts7.isStringLiteral(node)) return node.text;
5208
- if (ts7.isNumericLiteral(node)) return Number(node.text.replaceAll("_", ""));
5209
- if (ts7.isPrefixUnaryExpression(node) && node.operator === ts7.SyntaxKind.MinusToken && ts7.isNumericLiteral(node.operand)) {
5436
+ if (ts8.isStringLiteral(node)) return node.text;
5437
+ if (ts8.isNumericLiteral(node)) return Number(node.text.replaceAll("_", ""));
5438
+ if (ts8.isPrefixUnaryExpression(node) && node.operator === ts8.SyntaxKind.MinusToken && ts8.isNumericLiteral(node.operand)) {
5210
5439
  return -Number(node.operand.text.replaceAll("_", ""));
5211
5440
  }
5212
5441
  return void 0;
5213
5442
  }
5214
5443
  function isLiteralRoot(node) {
5215
- if (ts7.isPrefixUnaryExpression(node)) return literalOf(node) !== void 0;
5216
- return (ts7.isStringLiteral(node) || ts7.isNumericLiteral(node)) && !(ts7.isPrefixUnaryExpression(node.parent) && node.parent.operand === node);
5444
+ if (ts8.isPrefixUnaryExpression(node)) return literalOf(node) !== void 0;
5445
+ return (ts8.isStringLiteral(node) || ts8.isNumericLiteral(node)) && !(ts8.isPrefixUnaryExpression(node.parent) && node.parent.operand === node);
5217
5446
  }
5218
5447
  function invocation(node) {
5219
- if (ts7.isIdentifier(node.expression)) return { method: node.expression.text };
5220
- if (ts7.isPropertyAccessExpression(node.expression)) {
5448
+ if (ts8.isIdentifier(node.expression)) return { method: node.expression.text };
5449
+ if (ts8.isPropertyAccessExpression(node.expression)) {
5221
5450
  const receiver = node.expression.expression.getText();
5222
5451
  if (!/^[A-Za-z_$][\w$]*(?:\.[A-Za-z_$][\w$]*)?$/.test(receiver)) return void 0;
5223
5452
  return { method: node.expression.name.text, receiver };
@@ -5225,7 +5454,7 @@ function invocation(node) {
5225
5454
  return void 0;
5226
5455
  }
5227
5456
  function isPathname(node) {
5228
- return ts7.isPropertyAccessExpression(node) && node.name.text === "pathname";
5457
+ return ts8.isPropertyAccessExpression(node) && node.name.text === "pathname";
5229
5458
  }
5230
5459
  function contextFor(node, value, file, root) {
5231
5460
  if (typeof value === "number" && ignoredNumbers.has(value)) return void 0;
@@ -5234,7 +5463,7 @@ function contextFor(node, value, file, root) {
5234
5463
  const scope = featureOf(file, root);
5235
5464
  const isApiRoute = typeof value === "string" && value.startsWith("/api/") && !/[?&#\s]/.test(value);
5236
5465
  const route = () => ({ role: "api-route", family: "api-route" });
5237
- if (ts7.isPropertyAssignment(parent) && parent.initializer === node) {
5466
+ if (ts8.isPropertyAssignment(parent) && parent.initializer === node) {
5238
5467
  const name = nameOf(parent.name);
5239
5468
  if (!name) return void 0;
5240
5469
  if (name === "path" && isApiRoute) return route();
@@ -5243,14 +5472,14 @@ function contextFor(node, value, file, root) {
5243
5472
  if (isApiRoute && /route|path|endpoint/i.test(name)) return route();
5244
5473
  return { role: `property:${name}:${scope}`, family: `property:${name}` };
5245
5474
  }
5246
- if (ts7.isVariableDeclaration(parent) && parent.initializer === node && ts7.isIdentifier(parent.name)) {
5475
+ if (ts8.isVariableDeclaration(parent) && parent.initializer === node && ts8.isIdentifier(parent.name)) {
5247
5476
  if (typeof value === "number") return void 0;
5248
5477
  const name = parent.name.text;
5249
5478
  if (excludedProperties.has(name) || !semanticVariableName.test(name)) return void 0;
5250
5479
  if (isApiRoute && /route|path|endpoint/i.test(name)) return route();
5251
5480
  return { role: `variable:${name}:${scope}`, family: `variable:${name}` };
5252
5481
  }
5253
- if (ts7.isCallExpression(parent)) {
5482
+ if (ts8.isCallExpression(parent)) {
5254
5483
  const position = parent.arguments.findIndex((argument) => argument === node);
5255
5484
  if (position < 0) return void 0;
5256
5485
  const call = invocation(parent);
@@ -5269,45 +5498,45 @@ function contextFor(node, value, file, root) {
5269
5498
  return { role: `column:${scope}`, family: "column" };
5270
5499
  }
5271
5500
  }
5272
- if (isApiRoute && ts7.isBinaryExpression(parent) && (parent.operatorToken.kind === ts7.SyntaxKind.EqualsEqualsEqualsToken || parent.operatorToken.kind === ts7.SyntaxKind.ExclamationEqualsEqualsToken) && (parent.left === node && isPathname(parent.right) || parent.right === node && isPathname(parent.left))) {
5501
+ if (isApiRoute && ts8.isBinaryExpression(parent) && (parent.operatorToken.kind === ts8.SyntaxKind.EqualsEqualsEqualsToken || parent.operatorToken.kind === ts8.SyntaxKind.ExclamationEqualsEqualsToken) && (parent.left === node && isPathname(parent.right) || parent.right === node && isPathname(parent.left))) {
5273
5502
  return route();
5274
5503
  }
5275
- if (isApiRoute && ts7.isCallExpression(parent) && parent.arguments[0] === node && ts7.isPropertyAccessExpression(parent.expression) && parent.expression.name.text === "startsWith" && isPathname(parent.expression.expression)) {
5504
+ if (isApiRoute && ts8.isCallExpression(parent) && parent.arguments[0] === node && ts8.isPropertyAccessExpression(parent.expression) && parent.expression.name.text === "startsWith" && isPathname(parent.expression.expression)) {
5276
5505
  return route();
5277
5506
  }
5278
5507
  return void 0;
5279
5508
  }
5280
5509
  function isExported2(node) {
5281
- return ts7.canHaveModifiers(node) && (ts7.getModifiers(node) ?? []).some((modifier) => modifier.kind === ts7.SyntaxKind.ExportKeyword);
5510
+ return ts8.canHaveModifiers(node) && (ts8.getModifiers(node) ?? []).some((modifier) => modifier.kind === ts8.SyntaxKind.ExportKeyword);
5282
5511
  }
5283
5512
  function parse(file, root, output) {
5284
5513
  if (!isProductionSource(file, root)) return;
5285
- const source = ts7.createSourceFile(
5514
+ const source = ts8.createSourceFile(
5286
5515
  file,
5287
- readFileSync8(file, "utf8"),
5288
- ts7.ScriptTarget.Latest,
5516
+ readFileSync9(file, "utf8"),
5517
+ ts8.ScriptTarget.Latest,
5289
5518
  true,
5290
- file.endsWith(".tsx") || file.endsWith(".jsx") ? ts7.ScriptKind.TSX : ts7.ScriptKind.TS
5519
+ file.endsWith(".tsx") || file.endsWith(".jsx") ? ts8.ScriptKind.TSX : ts8.ScriptKind.TS
5291
5520
  );
5292
- const inConstants = path39.relative(root, file).split(path39.sep).includes("constants");
5521
+ const inConstants = path40.relative(root, file).split(path40.sep).includes("constants");
5293
5522
  for (const statement of source.statements) {
5294
- if (inConstants && ts7.isEnumDeclaration(statement) && isExported2(statement)) {
5523
+ if (inConstants && ts8.isEnumDeclaration(statement) && isExported2(statement)) {
5295
5524
  for (const member of statement.members) {
5296
5525
  const value = member.initializer && literalOf(member.initializer);
5297
- const memberName9 = nameOf(member.name);
5298
- if (value === void 0 || !memberName9) continue;
5526
+ const memberName10 = nameOf(member.name);
5527
+ if (value === void 0 || !memberName10) continue;
5299
5528
  output.canonicals.push({
5300
5529
  file,
5301
- name: memberName9,
5530
+ name: memberName10,
5302
5531
  owner: statement.name.text,
5303
5532
  kind: typeof value === "string" ? "string" : "number",
5304
5533
  value
5305
5534
  });
5306
5535
  }
5307
5536
  }
5308
- if (inConstants && ts7.isVariableStatement(statement) && isExported2(statement)) {
5537
+ if (inConstants && ts8.isVariableStatement(statement) && isExported2(statement)) {
5309
5538
  for (const declaration of statement.declarationList.declarations) {
5310
- if (!ts7.isIdentifier(declaration.name) || !declaration.initializer) continue;
5539
+ if (!ts8.isIdentifier(declaration.name) || !declaration.initializer) continue;
5311
5540
  const value = literalOf(declaration.initializer);
5312
5541
  if (value === void 0) continue;
5313
5542
  output.canonicals.push({
@@ -5326,7 +5555,7 @@ function parse(file, root, output) {
5326
5555
  const semantic = contextFor(node, value, file, root);
5327
5556
  if (semantic) {
5328
5557
  const declaration = node.parent;
5329
- const isCanonicalDefinition = inConstants && (ts7.isVariableDeclaration(declaration) && ts7.isVariableStatement(declaration.parent.parent) && isExported2(declaration.parent.parent) || ts7.isEnumMember(declaration));
5558
+ const isCanonicalDefinition = inConstants && (ts8.isVariableDeclaration(declaration) && ts8.isVariableStatement(declaration.parent.parent) && isExported2(declaration.parent.parent) || ts8.isEnumMember(declaration));
5330
5559
  if ((!inConstants || semantic.family === "api-route") && !isCanonicalDefinition) {
5331
5560
  const position = source.getLineAndCharacterOfPosition(node.getStart(source));
5332
5561
  output.uses.push({
@@ -5341,7 +5570,7 @@ function parse(file, root, output) {
5341
5570
  }
5342
5571
  }
5343
5572
  }
5344
- ts7.forEachChild(node, visit);
5573
+ ts8.forEachChild(node, visit);
5345
5574
  };
5346
5575
  visit(source);
5347
5576
  }
@@ -5361,8 +5590,8 @@ function getSemanticLiteralIndex(index) {
5361
5590
  }
5362
5591
 
5363
5592
  // eslint/rules/no-inline-runtime-literal.ts
5364
- var DOC4 = "See docs/next-codebase-guide/rules/constants-rule.md";
5365
- var MESSAGE2 = `Every runtime string or numeric value must use a named constant or enum member, including single-use values. Inline JSX className and canonical locale strings are exempt. ${DOC4}`;
5593
+ var DOC5 = "See docs/next-codebase-guide/rules/constants-rule.md";
5594
+ var MESSAGE2 = `Every runtime string or numeric value must use a named constant or enum member, including single-use values. Inline JSX className/data-component, canonical locale strings, and static Next.js matchers are exempt. ${DOC5}`;
5366
5595
  function isClassNameProp(node) {
5367
5596
  let current = node;
5368
5597
  while (current.parent) {
@@ -5375,15 +5604,43 @@ function isClassNameProp(node) {
5375
5604
  }
5376
5605
  return false;
5377
5606
  }
5378
- function containsInlineString(node) {
5379
- if (typeof node !== "object" || node === null || !("type" in node)) return false;
5380
- if (node.type === "TemplateLiteral") return true;
5381
- if (node.type === "Literal") return "value" in node && typeof node.value === "string";
5382
- if (node.type === "BinaryExpression") {
5383
- return "left" in node && containsInlineString(node.left) || "right" in node && containsInlineString(node.right);
5384
- }
5385
- if (node.type === "TSAsExpression" || node.type === "TSSatisfiesExpression") {
5386
- return "expression" in node && containsInlineString(node.expression);
5607
+ function isStaticDataComponentMarker(node) {
5608
+ const parent = node.parent;
5609
+ if (parent?.type !== "JSXAttribute" || parent.value !== node) return false;
5610
+ const name = parent.name;
5611
+ return typeof name === "object" && name !== null && "name" in name && name.name === "data-component";
5612
+ }
5613
+ function isStaticMatcherValue(node, root, file) {
5614
+ const relativeFile = path41.relative(root, file);
5615
+ if (relativeFile !== "middleware.ts" && relativeFile !== "proxy.ts") return false;
5616
+ let current = node;
5617
+ while (current.parent) {
5618
+ const parent = current.parent;
5619
+ if (parent.type === "ArrayExpression" && Array.isArray(parent.elements) && parent.elements.includes(current)) {
5620
+ current = parent;
5621
+ continue;
5622
+ }
5623
+ if (parent.type === "ObjectExpression" && Array.isArray(parent.properties) && parent.properties.includes(current)) {
5624
+ current = parent;
5625
+ continue;
5626
+ }
5627
+ if (parent.type !== "Property" || parent.value !== current || parent.computed) return false;
5628
+ const key = parent.key;
5629
+ if (typeof key !== "object" || key === null) return false;
5630
+ const isMatcher = "name" in key && key.name === "matcher" || "value" in key && key.value === "matcher";
5631
+ if (!isMatcher) {
5632
+ current = parent;
5633
+ continue;
5634
+ }
5635
+ const object = parent.parent;
5636
+ if (object?.type !== "ObjectExpression") return false;
5637
+ let configValue = object;
5638
+ while ((configValue.parent?.type === "TSAsExpression" || configValue.parent?.type === "TSSatisfiesExpression") && configValue.parent.expression === configValue) {
5639
+ configValue = configValue.parent;
5640
+ }
5641
+ const declaration = configValue.parent;
5642
+ const id = declaration?.id;
5643
+ return declaration?.type === "VariableDeclarator" && declaration.init === configValue && typeof id === "object" && id !== null && "name" in id && id.name === "config" && declaration.parent?.type === "VariableDeclaration" && declaration.parent.kind === "const" && declaration.parent.parent?.type === "ExportNamedDeclaration";
5387
5644
  }
5388
5645
  return false;
5389
5646
  }
@@ -5393,8 +5650,7 @@ function isNamedValue(node) {
5393
5650
  const parent2 = current.parent;
5394
5651
  const isTypeWrapper = parent2.type === "TSAsExpression" || parent2.type === "TSSatisfiesExpression";
5395
5652
  const isSignedNumber = parent2.type === "UnaryExpression" && parent2.argument === current && (parent2.operator === "-" || parent2.operator === "+");
5396
- const isArithmetic = parent2.type === "BinaryExpression" && typeof parent2.operator === "string" && ["+", "-", "*", "/", "%", "**", "<<", ">>", ">>>", "&", "|", "^"].includes(parent2.operator) && !containsInlineString(parent2.left) && !containsInlineString(parent2.right);
5397
- if (!isTypeWrapper && !isSignedNumber && !isArithmetic) break;
5653
+ if (!isTypeWrapper && !isSignedNumber) break;
5398
5654
  current = parent2;
5399
5655
  }
5400
5656
  const parent = current.parent;
@@ -5407,6 +5663,7 @@ function isNamedValue(node) {
5407
5663
  function isSyntacticString(node) {
5408
5664
  const parent = node.parent;
5409
5665
  if (!parent) return false;
5666
+ if (parent.type === "TSModuleDeclaration" && parent.id === node) return true;
5410
5667
  if (parent.type === "ImportDeclaration" || parent.type === "ExportNamedDeclaration" || parent.type === "ExportAllDeclaration" || parent.type === "ImportExpression" || parent.type === "TSLiteralType" || parent.type === "TSExternalModuleReference") {
5411
5668
  return true;
5412
5669
  }
@@ -5417,27 +5674,25 @@ function isSyntacticString(node) {
5417
5674
  return false;
5418
5675
  }
5419
5676
  function isRuntimeMockSource(file, root) {
5420
- const parts = path40.relative(root, file).split(path40.sep);
5421
- return parts.includes("mocks") && !parts.some((part) => part === "__tests__" || part === "__mocks__") && !/\.(?:test|spec|mock)\.[^.]+$/.test(path40.basename(file));
5677
+ const parts = path41.relative(root, file).split(path41.sep);
5678
+ return parts.includes("mocks") && !parts.some((part) => part === "__tests__" || part === "__mocks__") && !/\.(?:test|spec|mock)\.[^.]+$/.test(path41.basename(file));
5422
5679
  }
5423
5680
  function isCanonicalLocaleString(node, root, file) {
5424
- if (path40.relative(root, file) !== path40.join("locales", "index.ts")) return false;
5425
- let current = node;
5426
- let depth = 0;
5427
- while (current.parent?.type === "Property" && current.parent.value === current) {
5428
- const object = current.parent.parent;
5429
- if (object?.type !== "ObjectExpression") return false;
5430
- current = object;
5431
- depth += 1;
5432
- }
5433
- if (depth < 1 || depth > 2) return false;
5681
+ const relative = path41.relative(root, file).split(path41.sep);
5682
+ let namespace;
5683
+ if (relative.length === 2 && relative[0] === "locales" && relative[1] !== "index.ts" && /^[a-z][a-z0-9]*(?:-[a-z0-9]+)*\.ts$/.test(relative[1] ?? "")) {
5684
+ namespace = (relative[1] ?? "").slice(0, -3).replace(/-[a-z]/g, (match) => match.slice(1).toUpperCase());
5685
+ }
5686
+ if (!namespace) return false;
5687
+ if (node.parent?.type !== "Property" || node.parent.value !== node) return false;
5688
+ let current = node.parent.parent;
5689
+ if (current?.type !== "ObjectExpression") return false;
5434
5690
  while ((current.parent?.type === "TSAsExpression" || current.parent?.type === "TSSatisfiesExpression") && current.parent.expression === current) {
5435
5691
  current = current.parent;
5436
5692
  }
5437
5693
  const declaration = current.parent;
5438
- if (declaration?.type !== "VariableDeclarator" || declaration.init !== current) return false;
5439
- const id = declaration.id;
5440
- return typeof id === "object" && id !== null && "type" in id && id.type === "Identifier" && "name" in id && id.name === "locales" && declaration.parent?.type === "VariableDeclaration" && declaration.parent.kind === "const" && declaration.parent.parent?.type === "ExportNamedDeclaration";
5694
+ const id = declaration?.id;
5695
+ return declaration?.type === "VariableDeclarator" && declaration.init === current && typeof id === "object" && id !== null && "type" in id && id.type === "Identifier" && "name" in id && id.name === namespace && declaration.parent?.type === "VariableDeclaration" && declaration.parent.kind === "const" && declaration.parent.parent?.type === "ExportNamedDeclaration";
5441
5696
  }
5442
5697
  var noInlineRuntimeLiteralRule = {
5443
5698
  meta: {
@@ -5447,8 +5702,8 @@ var noInlineRuntimeLiteralRule = {
5447
5702
  },
5448
5703
  create(context) {
5449
5704
  const root = sourceRootOf(context);
5450
- const file = path40.resolve(context.filename);
5451
- if (!file.startsWith(root + path40.sep) || !isProductionSource(file, root) && !isRuntimeMockSource(file, root)) {
5705
+ const file = path41.resolve(context.filename);
5706
+ if (!file.startsWith(root + path41.sep) || !isProductionSource(file, root) && !isRuntimeMockSource(file, root)) {
5452
5707
  return {};
5453
5708
  }
5454
5709
  return {
@@ -5456,7 +5711,7 @@ var noInlineRuntimeLiteralRule = {
5456
5711
  if (typeof node.value !== "string" && typeof node.value !== "number" && typeof node.value !== "bigint" && !("bigint" in node && typeof node.bigint === "string")) {
5457
5712
  return;
5458
5713
  }
5459
- if (typeof node.value === "string" && (isClassNameProp(node) || isCanonicalLocaleString(node, root, file)) || isNamedValue(node) || isSyntacticString(node)) {
5714
+ if (typeof node.value === "string" && (isClassNameProp(node) || isStaticDataComponentMarker(node) || isCanonicalLocaleString(node, root, file)) || isStaticMatcherValue(node, root, file) || isNamedValue(node) || isSyntacticString(node)) {
5460
5715
  return;
5461
5716
  }
5462
5717
  context.report({ node, message: MESSAGE2 });
@@ -5495,7 +5750,7 @@ function isStaticValue(value) {
5495
5750
  }
5496
5751
  return false;
5497
5752
  }
5498
- function propertyName2(property) {
5753
+ function propertyName3(property) {
5499
5754
  if (!property.computed && property.key.type === "Identifier") return property.key.name;
5500
5755
  if (property.key.type === "Literal" && typeof property.key.value === "string") return property.key.value;
5501
5756
  return void 0;
@@ -5503,7 +5758,7 @@ function propertyName2(property) {
5503
5758
  function findStaticDeclaration(expression) {
5504
5759
  for (const property of expression.properties) {
5505
5760
  if (property.type !== "Property" || property.kind !== "init") continue;
5506
- const name = propertyName2(property);
5761
+ const name = propertyName3(property);
5507
5762
  if (!name) continue;
5508
5763
  if (isStaticValue(property.value)) return name;
5509
5764
  }
@@ -5545,8 +5800,8 @@ var noLiteralInlineStyleRule = {
5545
5800
  };
5546
5801
 
5547
5802
  // eslint/rules/no-mixed-concerns.ts
5548
- import { readFileSync as readFileSync9 } from "fs";
5549
- import path41 from "path";
5803
+ import { readFileSync as readFileSync10 } from "fs";
5804
+ import path42 from "path";
5550
5805
  var noMixedConcernsRule = {
5551
5806
  meta: {
5552
5807
  schema: [],
@@ -5570,7 +5825,7 @@ var noMixedConcernsRule = {
5570
5825
  if (components.length > 1) return;
5571
5826
  const componentName = components[0]?.name;
5572
5827
  if (!componentName) return;
5573
- const file = path41.resolve(context.filename);
5828
+ const file = path42.resolve(context.filename);
5574
5829
  const sourceRoot = sourceRootOf(context);
5575
5830
  const index = getProjectIndex(sourceRoot);
5576
5831
  const componentConsumers = index?.symbolConsumers.get(symbolKey(file, componentName)) ?? /* @__PURE__ */ new Set();
@@ -5581,6 +5836,7 @@ var noMixedConcernsRule = {
5581
5836
  if (name === componentName) return;
5582
5837
  if (isNextPageOrLayout) {
5583
5838
  if (["metadata", "viewport", "generateMetadata", "generateViewport"].includes(name)) return;
5839
+ if (name === "generateStaticParams" && /\[[^\]]+\]/.test(context.filename)) return;
5584
5840
  context.report({
5585
5841
  loc,
5586
5842
  message: `Next.js page/layout files cannot export "${name}". Use a separate module for supporting values.`
@@ -5614,7 +5870,7 @@ var noMixedConcernsRule = {
5614
5870
  continue;
5615
5871
  }
5616
5872
  const target = typeof statement.source?.value === "string" ? resolveSpecifier(file, statement.source.value, sourceRoot) : void 0;
5617
- const forwardedComponents = target?.endsWith(".tsx") ? parseComponentInfo(readFileSync9(target, "utf8"), target).map((component) => component.name) : [];
5873
+ const forwardedComponents = target?.endsWith(".tsx") ? parseComponentInfo(readFileSync10(target, "utf8"), target).map((component) => component.name) : [];
5618
5874
  for (const specifier of statement.specifiers) {
5619
5875
  if (/^type\b/.test(context.sourceCode.getText(specifier))) continue;
5620
5876
  if (specifier.local.type !== "Identifier") continue;
@@ -5648,11 +5904,11 @@ var noMixedConcernsRule = {
5648
5904
  };
5649
5905
 
5650
5906
  // eslint/rules/no-redundant-alias.ts
5651
- import path43 from "path";
5907
+ import path44 from "path";
5652
5908
 
5653
5909
  // eslint/rules/contract-ownership.ts
5654
- import path42 from "path";
5655
- import ts8 from "typescript";
5910
+ import path43 from "path";
5911
+ import ts9 from "typescript";
5656
5912
  function isTsProgram(value) {
5657
5913
  return typeof value === "object" && value !== null && "getTypeChecker" in value && typeof value.getTypeChecker === "function" && "getSourceFiles" in value && typeof value.getSourceFiles === "function";
5658
5914
  }
@@ -5670,8 +5926,8 @@ function normalizePath(value) {
5670
5926
  return value.replaceAll("\\", "/").toLowerCase();
5671
5927
  }
5672
5928
  function isWithin2(root, file) {
5673
- const relative = path42.relative(root, file);
5674
- return relative === "" || !relative.startsWith("..") && !path42.isAbsolute(relative);
5929
+ const relative = path43.relative(root, file);
5930
+ return relative === "" || !relative.startsWith("..") && !path43.isAbsolute(relative);
5675
5931
  }
5676
5932
  function mergeOwnership(values) {
5677
5933
  if (values.length === 0 || values.includes("unknown")) return "unknown";
@@ -5686,11 +5942,11 @@ function endpointOwnership(pathValue) {
5686
5942
  return "unknown";
5687
5943
  }
5688
5944
  function resolvedSymbol(checker, symbol) {
5689
- return symbol.flags === ts8.SymbolFlags.Alias ? checker.getAliasedSymbol(symbol) : symbol;
5945
+ return symbol.flags === ts9.SymbolFlags.Alias ? checker.getAliasedSymbol(symbol) : symbol;
5690
5946
  }
5691
- function propertyName3(node) {
5947
+ function propertyName4(node) {
5692
5948
  if (!node) return void 0;
5693
- if (ts8.isIdentifier(node) || ts8.isStringLiteral(node) || ts8.isNumericLiteral(node)) return node.text;
5949
+ if (ts9.isIdentifier(node) || ts9.isStringLiteral(node) || ts9.isNumericLiteral(node)) return node.text;
5694
5950
  return void 0;
5695
5951
  }
5696
5952
  var ContractOwnershipIndex = class {
@@ -5714,7 +5970,7 @@ var ContractOwnershipIndex = class {
5714
5970
  }
5715
5971
  if (declarations.length > 0) return this.endpointFromDeclarations(declarations);
5716
5972
  let object;
5717
- if (ts8.isPropertyAccessExpression(node) || ts8.isElementAccessExpression(node)) object = node.expression;
5973
+ if (ts9.isPropertyAccessExpression(node) || ts9.isElementAccessExpression(node)) object = node.expression;
5718
5974
  if (!object) return { kind: "missing", ownership: "unknown" };
5719
5975
  const type = this.checker.getTypeAtLocation(object);
5720
5976
  const typeDeclarations = this.typeDeclarations(type);
@@ -5722,7 +5978,7 @@ var ContractOwnershipIndex = class {
5722
5978
  return this.endpointFromDeclarations(typeDeclarations);
5723
5979
  }
5724
5980
  sourceBinding(node, name) {
5725
- if (!ts8.isVariableDeclaration(node) || !node.initializer) {
5981
+ if (!ts9.isVariableDeclaration(node) || !node.initializer) {
5726
5982
  return { kind: "missing", ownership: "unknown" };
5727
5983
  }
5728
5984
  const sourceType = this.checker.getTypeAtLocation(node.initializer);
@@ -5731,11 +5987,11 @@ var ContractOwnershipIndex = class {
5731
5987
  return this.endpointFromDeclarations(declarations);
5732
5988
  }
5733
5989
  targetProperty(node, name) {
5734
- if (!ts8.isPropertyAssignment(node) && !ts8.isShorthandPropertyAssignment(node)) {
5990
+ if (!ts9.isPropertyAssignment(node) && !ts9.isShorthandPropertyAssignment(node)) {
5735
5991
  return { kind: "missing", ownership: "unknown" };
5736
5992
  }
5737
5993
  const object = node.parent;
5738
- if (!ts8.isObjectLiteralExpression(object)) return { kind: "missing", ownership: "unknown" };
5994
+ if (!ts9.isObjectLiteralExpression(object)) return { kind: "missing", ownership: "unknown" };
5739
5995
  const contextualType = this.checker.getContextualType(object);
5740
5996
  if (!contextualType) return { kind: "missing", ownership: "unknown" };
5741
5997
  const declarations = this.propertyDeclarations(contextualType, name);
@@ -5743,8 +5999,8 @@ var ContractOwnershipIndex = class {
5743
5999
  return this.endpointFromDeclarations(declarations);
5744
6000
  }
5745
6001
  memberNameSymbol(node) {
5746
- if (ts8.isPropertyAccessExpression(node)) return this.checker.getSymbolAtLocation(node.name);
5747
- if (ts8.isElementAccessExpression(node)) return this.checker.getSymbolAtLocation(node.argumentExpression);
6002
+ if (ts9.isPropertyAccessExpression(node)) return this.checker.getSymbolAtLocation(node.name);
6003
+ if (ts9.isElementAccessExpression(node)) return this.checker.getSymbolAtLocation(node.argumentExpression);
5748
6004
  return void 0;
5749
6005
  }
5750
6006
  propertyDeclarations(type, name) {
@@ -5774,14 +6030,14 @@ var ContractOwnershipIndex = class {
5774
6030
  if (declarations.some((declaration) => this.isDataContractField(declaration))) {
5775
6031
  return { kind: "data-contract", ownership };
5776
6032
  }
5777
- if (declarations.some((declaration) => ts8.isPropertySignature(declaration) || ts8.isPropertyDeclaration(declaration))) {
6033
+ if (declarations.some((declaration) => ts9.isPropertySignature(declaration) || ts9.isPropertyDeclaration(declaration))) {
5778
6034
  return { kind: "typed-local", ownership };
5779
6035
  }
5780
6036
  return { kind: "non-contract", ownership };
5781
6037
  }
5782
6038
  isDataContractField(declaration) {
5783
6039
  if (this.isZodSchemaField(declaration)) return true;
5784
- if (!ts8.isPropertySignature(declaration) && !ts8.isPropertyDeclaration(declaration)) return false;
6040
+ if (!ts9.isPropertySignature(declaration) && !ts9.isPropertyDeclaration(declaration)) return false;
5785
6041
  const fileName = normalizePath(declaration.getSourceFile().fileName);
5786
6042
  return /(?:^|\/)database(?:[-.]generated)?\.ts$/u.test(fileName);
5787
6043
  }
@@ -5790,10 +6046,10 @@ var ContractOwnershipIndex = class {
5790
6046
  return this.checker.getPropertyOfType(type, "_zod") !== void 0 && this.checker.getPropertyOfType(type, "parse") !== void 0 && this.checker.getPropertyOfType(type, "safeParse") !== void 0;
5791
6047
  }
5792
6048
  isZodSchemaField(declaration) {
5793
- if (!ts8.isPropertyAssignment(declaration)) return false;
6049
+ if (!ts9.isPropertyAssignment(declaration)) return false;
5794
6050
  let current = declaration.parent;
5795
- while (!ts8.isSourceFile(current)) {
5796
- if (ts8.isVariableDeclaration(current) && ts8.isIdentifier(current.name) && current.name.text.endsWith("Schema")) {
6051
+ while (!ts9.isSourceFile(current)) {
6052
+ if (ts9.isVariableDeclaration(current) && ts9.isIdentifier(current.name) && current.name.text.endsWith("Schema")) {
5797
6053
  return true;
5798
6054
  }
5799
6055
  current = current.parent;
@@ -5811,12 +6067,12 @@ var ContractOwnershipIndex = class {
5811
6067
  const normalized = normalizePath(fileName);
5812
6068
  if (/\/typescript\/lib\/lib\.[^/]+\.d\.ts$/u.test(normalized)) return "platform";
5813
6069
  if (normalized.includes("/node_modules/")) return "third-party";
5814
- if (isWithin2(this.cwd, path42.resolve(fileName))) return "first-party";
6070
+ if (isWithin2(this.cwd, path43.resolve(fileName))) return "first-party";
5815
6071
  return "unknown";
5816
6072
  }
5817
6073
  schemaOwnership(declaration) {
5818
6074
  let current = declaration;
5819
- while (!ts8.isSourceFile(current)) {
6075
+ while (!ts9.isSourceFile(current)) {
5820
6076
  const ownership = this.schemaNodeOwnership.get(current);
5821
6077
  if (ownership !== void 0) return ownership;
5822
6078
  current = current.parent;
@@ -5825,31 +6081,31 @@ var ContractOwnershipIndex = class {
5825
6081
  }
5826
6082
  indexApiContracts() {
5827
6083
  for (const sourceFile of this.program.getSourceFiles()) {
5828
- if (sourceFile.isDeclarationFile || !isWithin2(this.cwd, path42.resolve(sourceFile.fileName))) continue;
6084
+ if (sourceFile.isDeclarationFile || !isWithin2(this.cwd, path43.resolve(sourceFile.fileName))) continue;
5829
6085
  const visit = (node) => {
5830
- if (ts8.isCallExpression(node) && this.isDefineApiContractCall(node)) this.indexApiContractCall(node);
5831
- ts8.forEachChild(node, visit);
6086
+ if (ts9.isCallExpression(node) && this.isDefineApiContractCall(node)) this.indexApiContractCall(node);
6087
+ ts9.forEachChild(node, visit);
5832
6088
  };
5833
6089
  visit(sourceFile);
5834
6090
  }
5835
6091
  }
5836
6092
  isDefineApiContractCall(node) {
5837
- if (ts8.isIdentifier(node.expression)) return node.expression.text === "defineApiContract";
5838
- return ts8.isPropertyAccessExpression(node.expression) && node.expression.name.text === "defineApiContract";
6093
+ if (ts9.isIdentifier(node.expression)) return node.expression.text === "defineApiContract";
6094
+ return ts9.isPropertyAccessExpression(node.expression) && node.expression.name.text === "defineApiContract";
5839
6095
  }
5840
6096
  indexApiContractCall(node) {
5841
6097
  const argument = node.arguments[0];
5842
- if (!argument || !ts8.isObjectLiteralExpression(argument)) return;
6098
+ if (!argument || !ts9.isObjectLiteralExpression(argument)) return;
5843
6099
  let pathExpression;
5844
6100
  const schemaExpressions = [];
5845
6101
  for (const property of argument.properties) {
5846
- if (ts8.isPropertyAssignment(property)) {
5847
- const name = propertyName3(property.name);
6102
+ if (ts9.isPropertyAssignment(property)) {
6103
+ const name = propertyName4(property.name);
5848
6104
  if (name === "path") pathExpression = property.initializer;
5849
6105
  if (name === "requestSchema" || name === "responseSchema") schemaExpressions.push(property.initializer);
5850
6106
  continue;
5851
6107
  }
5852
- if (ts8.isShorthandPropertyAssignment(property)) {
6108
+ if (ts9.isShorthandPropertyAssignment(property)) {
5853
6109
  const name = property.name.text;
5854
6110
  if (name === "path") pathExpression = property.name;
5855
6111
  if (name === "requestSchema" || name === "responseSchema") schemaExpressions.push(property.name);
@@ -5863,13 +6119,13 @@ var ContractOwnershipIndex = class {
5863
6119
  }
5864
6120
  staticString(node, seen) {
5865
6121
  if (!node) return void 0;
5866
- if (ts8.isStringLiteralLike(node)) return node.text;
5867
- if (ts8.isIdentifier(node)) {
6122
+ if (ts9.isStringLiteralLike(node)) return node.text;
6123
+ if (ts9.isIdentifier(node)) {
5868
6124
  const symbol = this.checker.getSymbolAtLocation(node);
5869
6125
  if (!symbol || seen.has(symbol)) return void 0;
5870
6126
  seen.add(symbol);
5871
6127
  for (const declaration of resolvedSymbol(this.checker, symbol).declarations ?? []) {
5872
- if (ts8.isVariableDeclaration(declaration) && declaration.initializer) {
6128
+ if (ts9.isVariableDeclaration(declaration) && declaration.initializer) {
5873
6129
  const value = this.staticString(declaration.initializer, seen);
5874
6130
  if (value !== void 0) return value;
5875
6131
  }
@@ -5887,20 +6143,20 @@ var ContractOwnershipIndex = class {
5887
6143
  this.followSchemaDeclaration(declaration, ownership, seen);
5888
6144
  }
5889
6145
  }
5890
- ts8.forEachChild(node, (child) => {
6146
+ ts9.forEachChild(node, (child) => {
5891
6147
  this.markSchemaExpression(child, ownership, seen);
5892
6148
  });
5893
6149
  }
5894
6150
  schemaReferenceSymbol(node) {
5895
- if (ts8.isIdentifier(node)) {
6151
+ if (ts9.isIdentifier(node)) {
5896
6152
  if (!node.text.endsWith("Schema")) return void 0;
5897
6153
  return this.checker.getSymbolAtLocation(node);
5898
6154
  }
5899
- if (ts8.isPropertyAccessExpression(node)) {
6155
+ if (ts9.isPropertyAccessExpression(node)) {
5900
6156
  if (!node.name.text.endsWith("Schema")) return void 0;
5901
6157
  return this.checker.getSymbolAtLocation(node.name);
5902
6158
  }
5903
- if (ts8.isElementAccessExpression(node) && ts8.isStringLiteralLike(node.argumentExpression)) {
6159
+ if (ts9.isElementAccessExpression(node) && ts9.isStringLiteralLike(node.argumentExpression)) {
5904
6160
  if (!node.argumentExpression.text.endsWith("Schema")) return void 0;
5905
6161
  return this.checker.getSymbolAtLocation(node.argumentExpression);
5906
6162
  }
@@ -5908,15 +6164,15 @@ var ContractOwnershipIndex = class {
5908
6164
  }
5909
6165
  followSchemaDeclaration(declaration, ownership, seen) {
5910
6166
  this.setSchemaOwnership(declaration, ownership);
5911
- if (ts8.isVariableDeclaration(declaration) && declaration.initializer) {
6167
+ if (ts9.isVariableDeclaration(declaration) && declaration.initializer) {
5912
6168
  this.markSchemaExpression(declaration.initializer, ownership, seen);
5913
6169
  return;
5914
6170
  }
5915
- if (ts8.isPropertyAssignment(declaration)) {
6171
+ if (ts9.isPropertyAssignment(declaration)) {
5916
6172
  this.markSchemaExpression(declaration.initializer, ownership, seen);
5917
6173
  return;
5918
6174
  }
5919
- if (ts8.isShorthandPropertyAssignment(declaration)) {
6175
+ if (ts9.isShorthandPropertyAssignment(declaration)) {
5920
6176
  const valueSymbol = this.checker.getShorthandAssignmentValueSymbol(declaration);
5921
6177
  if (!valueSymbol || seen.has(valueSymbol)) return;
5922
6178
  seen.add(valueSymbol);
@@ -5960,7 +6216,7 @@ function contractOwnershipResolver(context) {
5960
6216
  }
5961
6217
 
5962
6218
  // eslint/rules/no-redundant-alias.ts
5963
- var DOC5 = "See docs/next-codebase-guide/rules/redundant-aliases-rule.md";
6219
+ var DOC6 = "See docs/next-codebase-guide/rules/redundant-aliases-rule.md";
5964
6220
  var VALUE_SENTINELS = /* @__PURE__ */ new Set(["undefined", "NaN", "Infinity"]);
5965
6221
  var HTTP_METHODS = /* @__PURE__ */ new Set(["GET", "POST", "PUT", "PATCH", "DELETE", "HEAD", "OPTIONS"]);
5966
6222
  var FRAMEWORK_MAPPING_KEYS = /* @__PURE__ */ new Set(["default", "apiRoutePath"]);
@@ -5993,14 +6249,14 @@ function aliasedTypeName(annotation) {
5993
6249
  function aliasMessage(alias, source) {
5994
6250
  const aliasName = alias ?? "This declaration";
5995
6251
  const sourceName = source ?? "the original symbol";
5996
- return `"${aliasName}" only renames "${sourceName}". Use "${sourceName}" directly or rename the original symbol and its consumers. ${DOC5}`;
6252
+ return `"${aliasName}" only renames "${sourceName}". Use "${sourceName}" directly or rename the original symbol and its consumers. ${DOC6}`;
5997
6253
  }
5998
6254
  function bindingAliasMessage(alias, source) {
5999
- return `"${alias}" renames "${source}" while creating a binding. Keep the original name and map it only at the object boundary. ${DOC5}`;
6255
+ return `"${alias}" renames "${source}" while creating a binding. Keep the original name and map it only at the object boundary. ${DOC6}`;
6000
6256
  }
6001
- function objectPropertyMessage(propertyName5, source) {
6002
- if (source === propertyName5) return `Use property shorthand for "${propertyName5}". ${DOC5}`;
6003
- return `"${propertyName5}" maps the local "${source}". Keep the local name or map directly from its source object instead. ${DOC5}`;
6257
+ function objectPropertyMessage(propertyName6, source) {
6258
+ if (source === propertyName6) return `Use property shorthand for "${propertyName6}". ${DOC6}`;
6259
+ return `"${propertyName6}" maps the local "${source}". Keep the local name or map directly from its source object instead. ${DOC6}`;
6004
6260
  }
6005
6261
  function normalizePropertyName(name) {
6006
6262
  return name.replace(/[-_\s]/g, "").toLowerCase();
@@ -6013,12 +6269,12 @@ function memberPropertyName2(node) {
6013
6269
  }
6014
6270
  return void 0;
6015
6271
  }
6016
- function isNamedMemberValue(propertyName5) {
6017
- return /^[A-Z]/.test(propertyName5);
6272
+ function isNamedMemberValue(propertyName6) {
6273
+ return /^[A-Z]/.test(propertyName6);
6018
6274
  }
6019
- function isQualifiedSourceField(propertyName5, sourceMember, sourcePropertyName) {
6275
+ function isQualifiedSourceField(propertyName6, sourceMember, sourcePropertyName) {
6020
6276
  if (sourceMember.type !== "MemberExpression" || sourceMember.object.type !== "Identifier") return false;
6021
- return normalizePropertyName(propertyName5) === normalizePropertyName(`${sourceMember.object.name}${sourcePropertyName}`);
6277
+ return normalizePropertyName(propertyName6) === normalizePropertyName(`${sourceMember.object.name}${sourcePropertyName}`);
6022
6278
  }
6023
6279
  function isInsideSchemaDeclaration(node) {
6024
6280
  let current = node;
@@ -6030,11 +6286,11 @@ function isInsideSchemaDeclaration(node) {
6030
6286
  }
6031
6287
  return false;
6032
6288
  }
6033
- function semanticMappingMessage(propertyName5, sourcePropertyName) {
6034
- return `"${propertyName5}" maps from "${sourcePropertyName}" between first-party contracts. Use one canonical field name across the contracts. ${DOC5}`;
6289
+ function semanticMappingMessage(propertyName6, sourcePropertyName) {
6290
+ return `"${propertyName6}" maps from "${sourcePropertyName}" between first-party contracts. Use one canonical field name across the contracts. ${DOC6}`;
6035
6291
  }
6036
- function unknownContractOwnershipMessage(propertyName5, sourcePropertyName) {
6037
- return `Cannot determine contract ownership for mapping "${propertyName5}" from "${sourcePropertyName}". Define or propagate a concrete contract, make the boundary schema explicit, or connect a mirrored external schema to its defineApiContract. ${DOC5}`;
6292
+ function unknownContractOwnershipMessage(propertyName6, sourcePropertyName) {
6293
+ return `Cannot determine contract ownership for mapping "${propertyName6}" from "${sourcePropertyName}". Define or propagate a concrete contract, make the boundary schema explicit, or connect a mirrored external schema to its defineApiContract. ${DOC6}`;
6038
6294
  }
6039
6295
  function destructuredBindingSource(context, identifier) {
6040
6296
  const initialScope = context.sourceCode.getScope(identifier);
@@ -6061,7 +6317,7 @@ function destructuredBindingSource(context, identifier) {
6061
6317
  }
6062
6318
  return void 0;
6063
6319
  }
6064
- function contractMappingViolation(propertyName5, sourcePropertyName, sourceResolution, targetResolution) {
6320
+ function contractMappingViolation(propertyName6, sourcePropertyName, sourceResolution, targetResolution) {
6065
6321
  if (sourceResolution.kind === "non-contract" || targetResolution.kind === "non-contract") return void 0;
6066
6322
  if ((sourceResolution.ownership === "third-party" || sourceResolution.ownership === "platform") && targetResolution.kind !== "missing") {
6067
6323
  return void 0;
@@ -6072,11 +6328,11 @@ function contractMappingViolation(propertyName5, sourcePropertyName, sourceResol
6072
6328
  const hasDataContract = sourceResolution.kind === "data-contract" || targetResolution.kind === "data-contract";
6073
6329
  if (!hasDataContract) return void 0;
6074
6330
  if (sourceResolution.kind === "missing" || targetResolution.kind === "missing" || sourceResolution.ownership === "unknown" || targetResolution.ownership === "unknown") {
6075
- return unknownContractOwnershipMessage(propertyName5, sourcePropertyName);
6331
+ return unknownContractOwnershipMessage(propertyName6, sourcePropertyName);
6076
6332
  }
6077
6333
  if (sourceResolution.kind !== "data-contract") return void 0;
6078
6334
  if (sourceResolution.ownership !== "first-party" || targetResolution.ownership !== "first-party") return void 0;
6079
- return semanticMappingMessage(propertyName5, sourcePropertyName);
6335
+ return semanticMappingMessage(propertyName6, sourcePropertyName);
6080
6336
  }
6081
6337
  var noRedundantAliasRule = {
6082
6338
  meta: {
@@ -6096,7 +6352,7 @@ var noRedundantAliasRule = {
6096
6352
  if (declaration.type !== "VariableDeclaration" || declaration.kind !== "const") return;
6097
6353
  if (node.init.type === "Identifier") {
6098
6354
  const exported = declaration.parent.type === "ExportNamedDeclaration";
6099
- const frameworkRouteAlias = path43.basename(context.filename) === "route.ts" && exported && HTTP_METHODS.has(node.id.name);
6355
+ const frameworkRouteAlias = path44.basename(context.filename) === "route.ts" && exported && HTTP_METHODS.has(node.id.name);
6100
6356
  if (frameworkRouteAlias || VALUE_SENTINELS.has(node.init.name)) return;
6101
6357
  context.report({
6102
6358
  node,
@@ -6105,14 +6361,14 @@ var noRedundantAliasRule = {
6105
6361
  return;
6106
6362
  }
6107
6363
  if (node.init.type !== "MemberExpression") return;
6108
- let propertyName5;
6364
+ let propertyName6;
6109
6365
  if (!node.init.computed && node.init.property.type === "Identifier") {
6110
- propertyName5 = node.init.property.name;
6366
+ propertyName6 = node.init.property.name;
6111
6367
  }
6112
6368
  if (node.init.computed && node.init.property.type === "Literal" && typeof node.init.property.value === "string") {
6113
- propertyName5 = node.init.property.value;
6369
+ propertyName6 = node.init.property.value;
6114
6370
  }
6115
- if (propertyName5 === void 0 || propertyName5 === node.id.name) return;
6371
+ if (propertyName6 === void 0 || propertyName6 === node.id.name) return;
6116
6372
  context.report({
6117
6373
  node,
6118
6374
  message: bindingAliasMessage(node.id.name, context.sourceCode.getText(node.init))
@@ -6120,22 +6376,22 @@ var noRedundantAliasRule = {
6120
6376
  },
6121
6377
  Property(node) {
6122
6378
  if (node.computed) return;
6123
- let propertyName5;
6124
- if (node.key.type === "Identifier") propertyName5 = node.key.name;
6379
+ let propertyName6;
6380
+ if (node.key.type === "Identifier") propertyName6 = node.key.name;
6125
6381
  if (node.key.type === "Literal" && typeof node.key.value === "string") {
6126
- propertyName5 = node.key.value;
6382
+ propertyName6 = node.key.value;
6127
6383
  }
6128
- if (propertyName5 === void 0) return;
6384
+ if (propertyName6 === void 0) return;
6129
6385
  if (node.parent.type === "ObjectPattern") {
6130
6386
  let binding;
6131
6387
  if (node.value.type === "Identifier") binding = node.value;
6132
6388
  if (node.value.type === "AssignmentPattern" && node.value.left.type === "Identifier") {
6133
6389
  binding = node.value.left;
6134
6390
  }
6135
- if (!binding || binding.name === propertyName5) return;
6391
+ if (!binding || binding.name === propertyName6) return;
6136
6392
  context.report({
6137
6393
  node,
6138
- message: bindingAliasMessage(binding.name, propertyName5)
6394
+ message: bindingAliasMessage(binding.name, propertyName6)
6139
6395
  });
6140
6396
  return;
6141
6397
  }
@@ -6144,12 +6400,12 @@ var noRedundantAliasRule = {
6144
6400
  if (node.value.type === "Identifier") {
6145
6401
  if (node.shorthand) return;
6146
6402
  const source = node.value.name;
6147
- if (propertyName5 === source) {
6403
+ if (propertyName6 === source) {
6148
6404
  context.report({
6149
6405
  node,
6150
- message: objectPropertyMessage(propertyName5, source),
6406
+ message: objectPropertyMessage(propertyName6, source),
6151
6407
  fix(fixer) {
6152
- return fixer.replaceText(node, propertyName5);
6408
+ return fixer.replaceText(node, propertyName6);
6153
6409
  }
6154
6410
  });
6155
6411
  return;
@@ -6157,29 +6413,29 @@ var noRedundantAliasRule = {
6157
6413
  const bindingSource = destructuredBindingSource(context, node.value);
6158
6414
  if (!bindingSource || !ownershipResolver) return;
6159
6415
  const sourcePropertyName2 = bindingSource.propertyName;
6160
- if (normalizePropertyName(propertyName5) === normalizePropertyName(sourcePropertyName2)) return;
6161
- if (FRAMEWORK_MAPPING_KEYS.has(propertyName5) || isNamedMemberValue(sourcePropertyName2)) return;
6416
+ if (normalizePropertyName(propertyName6) === normalizePropertyName(sourcePropertyName2)) return;
6417
+ if (FRAMEWORK_MAPPING_KEYS.has(propertyName6) || isNamedMemberValue(sourcePropertyName2)) return;
6162
6418
  const sourceResolution2 = ownershipResolver.sourceBinding(bindingSource.declarator, sourcePropertyName2);
6163
- const targetResolution2 = ownershipResolver.targetProperty(node, propertyName5);
6419
+ const targetResolution2 = ownershipResolver.targetProperty(node, propertyName6);
6164
6420
  const hasDataContract = sourceResolution2.kind === "data-contract" || targetResolution2.kind === "data-contract";
6165
6421
  if (!hasDataContract) return;
6166
6422
  context.report({
6167
6423
  node,
6168
- message: contractMappingViolation(propertyName5, sourcePropertyName2, sourceResolution2, targetResolution2) ?? objectPropertyMessage(propertyName5, source)
6424
+ message: contractMappingViolation(propertyName6, sourcePropertyName2, sourceResolution2, targetResolution2) ?? objectPropertyMessage(propertyName6, source)
6169
6425
  });
6170
6426
  return;
6171
6427
  }
6172
6428
  if (node.value.type !== "MemberExpression") return;
6173
6429
  const sourcePropertyName = memberPropertyName2(node.value);
6174
6430
  if (sourcePropertyName === void 0) return;
6175
- if (normalizePropertyName(propertyName5) === normalizePropertyName(sourcePropertyName)) return;
6176
- if (FRAMEWORK_MAPPING_KEYS.has(propertyName5) || isNamedMemberValue(sourcePropertyName)) return;
6177
- if (isQualifiedSourceField(propertyName5, node.value, sourcePropertyName)) return;
6431
+ if (normalizePropertyName(propertyName6) === normalizePropertyName(sourcePropertyName)) return;
6432
+ if (FRAMEWORK_MAPPING_KEYS.has(propertyName6) || isNamedMemberValue(sourcePropertyName)) return;
6433
+ if (isQualifiedSourceField(propertyName6, node.value, sourcePropertyName)) return;
6178
6434
  if (!ownershipResolver) return;
6179
6435
  const sourceResolution = ownershipResolver.sourceMember(node.value);
6180
- const targetResolution = ownershipResolver.targetProperty(node, propertyName5);
6436
+ const targetResolution = ownershipResolver.targetProperty(node, propertyName6);
6181
6437
  const violation = contractMappingViolation(
6182
- propertyName5,
6438
+ propertyName6,
6183
6439
  sourcePropertyName,
6184
6440
  sourceResolution,
6185
6441
  targetResolution
@@ -6203,6 +6459,11 @@ var noRedundantAliasRule = {
6203
6459
  },
6204
6460
  ImportSpecifier(node) {
6205
6461
  if (node.imported.type !== "Identifier" || node.imported.name === node.local.name) return;
6462
+ const importDeclaration = node.parent;
6463
+ const source = importDeclaration.type === "ImportDeclaration" ? importDeclaration.source.value : void 0;
6464
+ if (typeof source === "string" && !source.startsWith(".") && !source.startsWith("/") && !source.startsWith("@/") && !source.startsWith("~/") && node.imported.name.includes("_") && /^[a-z][A-Za-z0-9]*$/.test(node.local.name)) {
6465
+ return;
6466
+ }
6206
6467
  context.report({
6207
6468
  node,
6208
6469
  message: bindingAliasMessage(node.local.name, node.imported.name)
@@ -6214,7 +6475,7 @@ var noRedundantAliasRule = {
6214
6475
  const source = specifier.local.name;
6215
6476
  const alias = specifier.exported.name;
6216
6477
  if (source === alias) continue;
6217
- const frameworkRouteAlias = path43.basename(context.filename) === "route.ts" && HTTP_METHODS.has(alias);
6478
+ const frameworkRouteAlias = path44.basename(context.filename) === "route.ts" && HTTP_METHODS.has(alias);
6218
6479
  if (frameworkRouteAlias) continue;
6219
6480
  context.report({
6220
6481
  node: specifier,
@@ -6239,7 +6500,7 @@ var noRedundantAliasRule = {
6239
6500
  };
6240
6501
 
6241
6502
  // eslint/rules/no-util-barrel.ts
6242
- import path44 from "path";
6503
+ import path45 from "path";
6243
6504
  var noUtilBarrelRule = {
6244
6505
  meta: {
6245
6506
  schema: [],
@@ -6249,7 +6510,7 @@ var noUtilBarrelRule = {
6249
6510
  }
6250
6511
  },
6251
6512
  create(context) {
6252
- const filename = path44.resolve(context.filename);
6513
+ const filename = path45.resolve(context.filename);
6253
6514
  const sourceRoot = sourceRootOf3(context, filename);
6254
6515
  return {
6255
6516
  Program(node) {
@@ -6258,7 +6519,7 @@ var noUtilBarrelRule = {
6258
6519
  if (!target) continue;
6259
6520
  const segments = target.replace(/\\/g, "/").split("/");
6260
6521
  const utilsIndex = segments.lastIndexOf("utils");
6261
- if (utilsIndex < 0 || !path44.basename(target).startsWith("index.")) continue;
6522
+ if (utilsIndex < 0 || !path45.basename(target).startsWith("index.")) continue;
6262
6523
  context.report({
6263
6524
  node,
6264
6525
  message: `Import utilities directly instead of through "${specifier}". See docs/next-codebase-guide/rules/utilities-rule.md`
@@ -6278,16 +6539,146 @@ function importSpecifiers2(source) {
6278
6539
  return specifiers;
6279
6540
  }
6280
6541
  function sourceRootOf3(context, filename) {
6281
- const marker = `${path44.sep}src${path44.sep}`;
6542
+ const marker = `${path45.sep}src${path45.sep}`;
6282
6543
  const srcIndex = filename.lastIndexOf(marker);
6283
6544
  if (srcIndex >= 0) return filename.slice(0, srcIndex + marker.length - 1);
6284
- return path44.resolve(context.cwd ?? process.cwd(), "src");
6545
+ return path45.resolve(context.cwd ?? process.cwd(), "src");
6285
6546
  }
6286
6547
 
6287
- // eslint/rules/package-json/exact-version.ts
6548
+ // eslint/rules/package-json/ci-checks.ts
6549
+ import { existsSync as existsSync6, readFileSync as readFileSync11, readdirSync as readdirSync4 } from "fs";
6550
+ import path46 from "path";
6551
+ import { parse as parse2 } from "yaml";
6552
+ function mapping(value) {
6553
+ return typeof value === "object" && value !== null && !Array.isArray(value) ? Object.fromEntries(Object.entries(value)) : void 0;
6554
+ }
6288
6555
  function memberName2(member) {
6289
6556
  return member.name.type === "String" ? member.name.value : member.name.name;
6290
6557
  }
6558
+ function scriptsOf(root) {
6559
+ if (root.type !== "Object") return /* @__PURE__ */ new Map();
6560
+ const scripts = root.members.find((member) => memberName2(member) === "scripts");
6561
+ const members = scripts?.value.type === "Object" ? scripts.value.members : [];
6562
+ return new Map(
6563
+ members.flatMap(
6564
+ (member) => member.value.type === "String" ? [[memberName2(member), member.value.value]] : []
6565
+ )
6566
+ );
6567
+ }
6568
+ function events(workflow) {
6569
+ const on = workflow.on;
6570
+ if (typeof on === "string") return { [on]: null };
6571
+ if (Array.isArray(on)) {
6572
+ return Object.fromEntries(
6573
+ on.filter((item) => typeof item === "string").map((item) => [item, null])
6574
+ );
6575
+ }
6576
+ return mapping(on) ?? {};
6577
+ }
6578
+ function branchesTrigger(workflow) {
6579
+ const push = events(workflow).push;
6580
+ const branches = mapping(push)?.branches;
6581
+ return typeof branches === "string" ? branches.length > 0 : Array.isArray(branches) && branches.some((branch) => typeof branch === "string" && branch.length > 0);
6582
+ }
6583
+ function jobs(workflow) {
6584
+ return mapping(workflow.jobs) ?? {};
6585
+ }
6586
+ function steps(job) {
6587
+ const entries = mapping(job)?.steps;
6588
+ return Array.isArray(entries) ? entries.flatMap((entry) => {
6589
+ const step = mapping(entry);
6590
+ return step ? [step] : [];
6591
+ }) : [];
6592
+ }
6593
+ function runsScript(run, name) {
6594
+ if (typeof run !== "string") return false;
6595
+ return new RegExp(`(?:^|[\\n;&|])\\s*npm\\s+run\\s+${name}(?=\\s|$)`).test(run);
6596
+ }
6597
+ function runsNpmCi(run) {
6598
+ return typeof run === "string" && /(?:^|[\n;&|])\s*npm\s+ci(?=\s|$)/.test(run);
6599
+ }
6600
+ function usesAction(value, action) {
6601
+ return typeof value === "string" && value.startsWith(`${action}@`);
6602
+ }
6603
+ function readWorkflows(dir) {
6604
+ const workflows = [];
6605
+ const errors = [];
6606
+ for (const file of readdirSync4(dir).filter((name) => /\.ya?ml$/i.test(name)).sort()) {
6607
+ try {
6608
+ const parsed = parse2(readFileSync11(path46.join(dir, file), "utf8"), { uniqueKeys: true });
6609
+ const content = mapping(parsed);
6610
+ if (!content) throw new Error("expected a YAML mapping");
6611
+ workflows.push(content);
6612
+ } catch (error) {
6613
+ errors.push(`${file}: ${error instanceof Error ? error.message : String(error)}`);
6614
+ }
6615
+ }
6616
+ return { workflows, errors };
6617
+ }
6618
+ var ciChecksRule = {
6619
+ meta: {
6620
+ schema: [],
6621
+ type: "problem",
6622
+ docs: {
6623
+ description: "Require GitHub Actions validation for pull requests and branch pushes."
6624
+ }
6625
+ },
6626
+ create(context) {
6627
+ return {
6628
+ Document(node) {
6629
+ if (!context.filename.endsWith("package.json")) return;
6630
+ const dir = path46.join(context.cwd, ".github", "workflows");
6631
+ if (!existsSync6(dir)) return;
6632
+ const report3 = (message) => {
6633
+ context.report({ node, message });
6634
+ };
6635
+ const { workflows, errors } = readWorkflows(dir);
6636
+ for (const error of errors) report3(`Invalid GitHub Actions workflow: ${error}`);
6637
+ const check = workflows.find(
6638
+ (workflow) => Object.hasOwn(events(workflow), "pull_request") && branchesTrigger(workflow)
6639
+ );
6640
+ if (!check) {
6641
+ report3("GitHub Actions must run shared checks for pull requests and branch pushes.");
6642
+ return;
6643
+ }
6644
+ const scripts = scriptsOf(node.body);
6645
+ const requiredScripts = ["format", "lint", "typecheck", "test:unit:coverage:check"];
6646
+ if (scripts.has("build")) requiredScripts.push("build");
6647
+ const checkJobs = Object.values(jobs(check));
6648
+ const allSteps = checkJobs.flatMap(steps);
6649
+ for (const job of checkJobs) {
6650
+ const jobSteps = steps(job);
6651
+ const firstCheck = jobSteps.findIndex((step) => requiredScripts.some((name) => runsScript(step.run, name)));
6652
+ if (firstCheck < 0) continue;
6653
+ const checkout = jobSteps.findIndex((step) => usesAction(step.uses, "actions/checkout"));
6654
+ const install = jobSteps.findIndex((step) => runsNpmCi(step.run));
6655
+ if (checkout < 0 || checkout >= firstCheck) {
6656
+ report3("GitHub Actions checks must check out the repository before running npm scripts.");
6657
+ }
6658
+ if (install < 0 || install >= firstCheck || checkout >= 0 && install <= checkout) {
6659
+ report3("GitHub Actions checks must install dependencies with npm ci.");
6660
+ }
6661
+ }
6662
+ for (const name of requiredScripts) {
6663
+ if (!allSteps.some((step) => runsScript(step.run, name))) {
6664
+ report3(`GitHub Actions checks must run npm run ${name}.`);
6665
+ }
6666
+ }
6667
+ const coverage = scripts.get("test:unit:coverage:check");
6668
+ if (!coverage || !/npm\s+run\s+test:unit:coverage(?=\s|$)/.test(coverage) || !coverage.includes("--coverage.thresholds.autoUpdate=false") || !/&&\s*git\s+diff\s+--exit-code/.test(coverage)) {
6669
+ report3(
6670
+ "package.json must declare test:unit:coverage:check that runs coverage with autoUpdate=false and verifies no Git diff."
6671
+ );
6672
+ }
6673
+ }
6674
+ };
6675
+ }
6676
+ };
6677
+
6678
+ // eslint/rules/package-json/exact-version.ts
6679
+ function memberName3(member) {
6680
+ return member.name.type === "String" ? member.name.value : member.name.name;
6681
+ }
6291
6682
  var EXACT_VERSION_PATTERN = /^\d+\.\d+\.\d+$/;
6292
6683
  function memberValue(member) {
6293
6684
  return member.value.type === "String" ? member.value.value : null;
@@ -6306,7 +6697,7 @@ var exactVersionRule = {
6306
6697
  const root = node.body;
6307
6698
  if (root.type !== "Object") return;
6308
6699
  for (const key of ["dependencies", "devDependencies"]) {
6309
- const section = root.members.find((member) => memberName2(member) === key);
6700
+ const section = root.members.find((member) => memberName3(member) === key);
6310
6701
  if (section?.value.type !== "Object") continue;
6311
6702
  for (const member of section.value.members) {
6312
6703
  const version = memberValue(member);
@@ -6314,7 +6705,7 @@ var exactVersionRule = {
6314
6705
  if (!EXACT_VERSION_PATTERN.test(version)) {
6315
6706
  context.report({
6316
6707
  node: member,
6317
- message: `${memberName2(member)} must pin an exact version (e.g. "1.2.3"), not a range or cap such as "${version}".`
6708
+ message: `${memberName3(member)} must pin an exact version (e.g. "1.2.3"), not a range or cap such as "${version}".`
6318
6709
  });
6319
6710
  }
6320
6711
  }
@@ -6325,7 +6716,7 @@ var exactVersionRule = {
6325
6716
  };
6326
6717
 
6327
6718
  // eslint/rules/package-json/lint-setup.ts
6328
- function memberName3(member) {
6719
+ function memberName4(member) {
6329
6720
  return member.name.type === "String" ? member.name.value : member.name.name;
6330
6721
  }
6331
6722
  function memberValue2(member) {
@@ -6367,9 +6758,9 @@ var lintSetupRule = {
6367
6758
  Document(node) {
6368
6759
  const root = node.body;
6369
6760
  if (root.type !== "Object") return;
6370
- const scripts = root.members.find((member) => memberName3(member) === "scripts");
6761
+ const scripts = root.members.find((member) => memberName4(member) === "scripts");
6371
6762
  const scriptMembers = scripts?.value.type === "Object" ? scripts.value.members : [];
6372
- const findScript = (name) => scriptMembers.find((member) => memberName3(member) === name);
6763
+ const findScript = (name) => scriptMembers.find((member) => memberName4(member) === name);
6373
6764
  const lint = findScript("lint");
6374
6765
  const lintCommand = memberValue2(lint);
6375
6766
  if (lintCommand === void 0 || !runsEslintDirectly(lintCommand) || !REPOSITORY_ARGUMENT_PATTERN.test(lintCommand)) {
@@ -6402,10 +6793,10 @@ var lintSetupRule = {
6402
6793
  message: 'package.json must declare a "format:staged" script that runs prettier with no repository-wide argument (e.g. "prettier --write").'
6403
6794
  });
6404
6795
  }
6405
- const lintStagedConfig = root.members.find((member) => memberName3(member) === "lint-staged");
6796
+ const lintStagedConfig = root.members.find((member) => memberName4(member) === "lint-staged");
6406
6797
  const stagedMembers = lintStagedConfig?.value.type === "Object" ? lintStagedConfig.value.members : [];
6407
6798
  const runsStagedScriptForGlob = (name, matchesGlob) => stagedMembers.some(
6408
- (member) => matchesGlob(memberName3(member)) && stringValues(member.value).some((command) => runsNamedScript(command, name))
6799
+ (member) => matchesGlob(memberName4(member)) && stringValues(member.value).some((command) => runsNamedScript(command, name))
6409
6800
  );
6410
6801
  const runsStagedScriptForExtension = (name, extension) => runsStagedScriptForGlob(name, (glob) => globIncludesExtension(glob, extension));
6411
6802
  const hasStagedSourceLint = runsStagedScriptForGlob("lint:staged", (glob) => SOURCE_GLOB_PATTERN.test(glob));
@@ -6456,13 +6847,13 @@ var NEXTJS_STACK_DEV_DEPENDENCIES = [
6456
6847
  "@testing-library/react",
6457
6848
  "@testing-library/dom"
6458
6849
  ];
6459
- function memberName4(member) {
6850
+ function memberName5(member) {
6460
6851
  return member.name.type === "String" ? member.name.value : member.name.name;
6461
6852
  }
6462
6853
  function sectionPackages(root, section) {
6463
- const member = root.type === "Object" ? root.members.find((entry) => memberName4(entry) === section) : void 0;
6854
+ const member = root.type === "Object" ? root.members.find((entry) => memberName5(entry) === section) : void 0;
6464
6855
  if (member?.value.type !== "Object") return /* @__PURE__ */ new Set();
6465
- return new Set(member.value.members.map(memberName4));
6856
+ return new Set(member.value.members.map(memberName5));
6466
6857
  }
6467
6858
  var nextjsStackRule = {
6468
6859
  meta: {
@@ -6499,9 +6890,9 @@ var nextjsStackRule = {
6499
6890
  };
6500
6891
 
6501
6892
  // eslint/rules/package-json/vitest-coverage.ts
6502
- import { existsSync as existsSync5, readFileSync as readFileSync10 } from "fs";
6503
- import path45 from "path";
6504
- function memberName5(member) {
6893
+ import { existsSync as existsSync7, readFileSync as readFileSync12 } from "fs";
6894
+ import path47 from "path";
6895
+ function memberName6(member) {
6505
6896
  return member.name.type === "String" ? member.name.value : member.name.name;
6506
6897
  }
6507
6898
  function memberValue3(member) {
@@ -6539,9 +6930,9 @@ var vitestCoverageRule = {
6539
6930
  Document(node) {
6540
6931
  const root = node.body;
6541
6932
  if (root.type !== "Object") return;
6542
- const devDependencies = root.members.find((member) => memberName5(member) === "devDependencies");
6933
+ const devDependencies = root.members.find((member) => memberName6(member) === "devDependencies");
6543
6934
  const devDependencyNames = new Set(
6544
- devDependencies?.value.type === "Object" ? devDependencies.value.members.map(memberName5) : []
6935
+ devDependencies?.value.type === "Object" ? devDependencies.value.members.map(memberName6) : []
6545
6936
  );
6546
6937
  if (!devDependencyNames.has("vitest")) {
6547
6938
  context.report({ node, message: "vitest must be listed in package.json as a devDependency." });
@@ -6552,9 +6943,9 @@ var vitestCoverageRule = {
6552
6943
  message: "@vitest/coverage-v8 must be listed in package.json as a devDependency."
6553
6944
  });
6554
6945
  }
6555
- const scripts = root.members.find((member) => memberName5(member) === "scripts");
6946
+ const scripts = root.members.find((member) => memberName6(member) === "scripts");
6556
6947
  const scriptMembers = scripts?.value.type === "Object" ? scripts.value.members : [];
6557
- const unit = scriptMembers.find((member) => memberName5(member) === "test:unit");
6948
+ const unit = scriptMembers.find((member) => memberName6(member) === "test:unit");
6558
6949
  const unitCommand = memberValue3(unit);
6559
6950
  if (unitCommand === void 0 || !/\bvitest\b/.test(unitCommand) || COVERAGE_FLAG_PATTERN.test(unitCommand)) {
6560
6951
  context.report({
@@ -6562,7 +6953,7 @@ var vitestCoverageRule = {
6562
6953
  message: 'package.json must declare a "test:unit" script that runs Vitest without coverage.'
6563
6954
  });
6564
6955
  }
6565
- const coverage = scriptMembers.find((member) => memberName5(member) === "test:unit:coverage");
6956
+ const coverage = scriptMembers.find((member) => memberName6(member) === "test:unit:coverage");
6566
6957
  const coverageCommand = memberValue3(coverage);
6567
6958
  if (coverageCommand === void 0 || !/\bvitest\b/.test(coverageCommand) || !COVERAGE_FLAG_PATTERN.test(coverageCommand)) {
6568
6959
  context.report({
@@ -6570,7 +6961,7 @@ var vitestCoverageRule = {
6570
6961
  message: 'package.json must declare a "test:unit:coverage" script that runs Vitest with coverage.'
6571
6962
  });
6572
6963
  }
6573
- const configName = VITEST_CONFIG_NAMES.find((name) => existsSync5(path45.join(context.cwd, name)));
6964
+ const configName = VITEST_CONFIG_NAMES.find((name) => existsSync7(path47.join(context.cwd, name)));
6574
6965
  if (!configName) {
6575
6966
  context.report({
6576
6967
  node,
@@ -6578,7 +6969,7 @@ var vitestCoverageRule = {
6578
6969
  });
6579
6970
  return;
6580
6971
  }
6581
- const content = readFileSync10(path45.join(context.cwd, configName), "utf8");
6972
+ const content = readFileSync12(path47.join(context.cwd, configName), "utf8");
6582
6973
  for (const metric of THRESHOLD_METRICS) {
6583
6974
  if (!new RegExp(`\\b${metric}\\s*:\\s*[1-9]\\d*`).test(content)) {
6584
6975
  context.report({ node, message: `${configName} must set a coverage threshold above zero for ${metric}.` });
@@ -6590,7 +6981,7 @@ var vitestCoverageRule = {
6590
6981
  message: `${configName} must enable coverage.thresholds.autoUpdate with true or the monotonic 0.1-point buffered formatter.`
6591
6982
  });
6592
6983
  }
6593
- const stagedTests = scriptMembers.find((member) => memberName5(member) === "test:unit:staged");
6984
+ const stagedTests = scriptMembers.find((member) => memberName6(member) === "test:unit:staged");
6594
6985
  const stagedTestsCommand = memberValue3(stagedTests);
6595
6986
  if (stagedTestsCommand === void 0 || !/\bvitest\b/.test(stagedTestsCommand) || !RELATED_PATTERN.test(stagedTestsCommand) || COVERAGE_FLAG_PATTERN.test(stagedTestsCommand)) {
6596
6987
  context.report({
@@ -6598,9 +6989,9 @@ var vitestCoverageRule = {
6598
6989
  message: 'package.json must declare a "test:unit:staged" script that runs vitest related without coverage.'
6599
6990
  });
6600
6991
  }
6601
- const lintStaged = root.members.find((member) => memberName5(member) === "lint-staged");
6992
+ const lintStaged = root.members.find((member) => memberName6(member) === "lint-staged");
6602
6993
  const hasStagedTests = lintStaged?.value.type === "Object" && lintStaged.value.members.some(
6603
- (member) => SOURCE_GLOB_PATTERN2.test(memberName5(member)) && stringValues2(member.value).some((command) => command.includes("npm run test:unit:staged"))
6994
+ (member) => SOURCE_GLOB_PATTERN2.test(memberName6(member)) && stringValues2(member.value).some((command) => command.includes("npm run test:unit:staged"))
6604
6995
  );
6605
6996
  if (!hasStagedTests) {
6606
6997
  context.report({
@@ -6615,6 +7006,7 @@ var vitestCoverageRule = {
6615
7006
 
6616
7007
  // eslint/rules/package-json/index.ts
6617
7008
  var repoPackageJsonRules = {
7009
+ "ci-checks": ciChecksRule,
6618
7010
  "exact-version": exactVersionRule,
6619
7011
  "lint-setup": lintSetupRule,
6620
7012
  "vitest-coverage": vitestCoverageRule
@@ -6624,8 +7016,8 @@ var nextjsPackageJsonRules = {
6624
7016
  };
6625
7017
 
6626
7018
  // eslint/rules/prefer-enum.ts
6627
- import path46 from "path";
6628
- import ts9 from "typescript";
7019
+ import path48 from "path";
7020
+ import ts10 from "typescript";
6629
7021
  function isConstAssertion(node) {
6630
7022
  const typeAnnotation = node.typeAnnotation;
6631
7023
  return typeAnnotation?.type === "TSTypeReference" && typeAnnotation.typeName?.type === "Identifier" && typeAnnotation.typeName.name === "const";
@@ -6647,7 +7039,7 @@ function isZodCall(node, method) {
6647
7039
  const { callee } = node;
6648
7040
  return callee?.type === "MemberExpression" && !callee.computed && callee.object.type === "Identifier" && callee.object.name === "z" && callee.property.type === "Identifier" && callee.property.name === method;
6649
7041
  }
6650
- function propertyName4(property) {
7042
+ function propertyName5(property) {
6651
7043
  if (property.computed) return void 0;
6652
7044
  if (property.key.type === "Identifier") return property.key.name;
6653
7045
  if (property.key.type === "Literal" && typeof property.key.value === "string") return property.key.value;
@@ -6658,7 +7050,7 @@ function rawZodDiscriminantLiteral(schemaCall, discriminator) {
6658
7050
  const shape = schemaCall.arguments[0];
6659
7051
  if (shape?.type !== "ObjectExpression") return void 0;
6660
7052
  for (const property of shape.properties) {
6661
- if (property.type !== "Property" || propertyName4(property) !== discriminator) continue;
7053
+ if (property.type !== "Property" || propertyName5(property) !== discriminator) continue;
6662
7054
  if (property.value.type !== "CallExpression" || !isZodCall(property.value, "literal")) return void 0;
6663
7055
  const literal = property.value.arguments[0];
6664
7056
  if (literal?.type === "Literal" && (typeof literal.value === "string" || typeof literal.value === "number")) {
@@ -6679,13 +7071,13 @@ function isLiteralTupleAssertion(node) {
6679
7071
  return values.every((value) => value !== void 0) && new Set(values).size >= 2;
6680
7072
  }
6681
7073
  function isTsLiteralTupleDeclaration(declaration) {
6682
- if (!ts9.isVariableDeclaration(declaration) || !declaration.initializer) return false;
7074
+ if (!ts10.isVariableDeclaration(declaration) || !declaration.initializer) return false;
6683
7075
  const init = declaration.initializer;
6684
- if (!ts9.isAsExpression(init) || !ts9.isTypeReferenceNode(init.type) || !ts9.isIdentifier(init.type.typeName) || init.type.typeName.text !== "const" || !ts9.isArrayLiteralExpression(init.expression) || init.expression.elements.length < 2) {
7076
+ if (!ts10.isAsExpression(init) || !ts10.isTypeReferenceNode(init.type) || !ts10.isIdentifier(init.type.typeName) || init.type.typeName.text !== "const" || !ts10.isArrayLiteralExpression(init.expression) || init.expression.elements.length < 2) {
6685
7077
  return false;
6686
7078
  }
6687
7079
  const values = init.expression.elements.map(
6688
- (element) => ts9.isStringLiteral(element) || ts9.isNumericLiteral(element) ? element.text : void 0
7080
+ (element) => ts10.isStringLiteral(element) || ts10.isNumericLiteral(element) ? element.text : void 0
6689
7081
  );
6690
7082
  return values.every((value) => value !== void 0) && new Set(values).size >= 2;
6691
7083
  }
@@ -6698,9 +7090,9 @@ var preferEnumRule = {
6698
7090
  }
6699
7091
  },
6700
7092
  create(context) {
6701
- const filename = path46.resolve(context.filename);
7093
+ const filename = path48.resolve(context.filename);
6702
7094
  const sourceRoot = sourceRootOf(context);
6703
- if (!filename.startsWith(sourceRoot + path46.sep)) return {};
7095
+ if (!filename.startsWith(sourceRoot + path48.sep)) return {};
6704
7096
  const objectSchemas = /* @__PURE__ */ new Map();
6705
7097
  const literalTuples = /* @__PURE__ */ new Set();
6706
7098
  const enumTupleUses = [];
@@ -6714,7 +7106,7 @@ var preferEnumRule = {
6714
7106
  const checker = services.program.getTypeChecker();
6715
7107
  const symbol = checker.getSymbolAtLocation(tsNode);
6716
7108
  if (!symbol) return false;
6717
- const original = symbol.flags === ts9.SymbolFlags.Alias ? checker.getAliasedSymbol(symbol) : symbol;
7109
+ const original = symbol.flags === ts10.SymbolFlags.Alias ? checker.getAliasedSymbol(symbol) : symbol;
6718
7110
  return (original.declarations ?? []).some(isTsLiteralTupleDeclaration);
6719
7111
  }
6720
7112
  return {
@@ -6809,8 +7201,8 @@ var preferEnumRule = {
6809
7201
  };
6810
7202
 
6811
7203
  // eslint/rules/prefer-object-destructuring.ts
6812
- import ts10 from "typescript";
6813
- var DOC6 = "See docs/next-codebase-guide/rules/redundant-aliases-rule.md";
7204
+ import ts11 from "typescript";
7205
+ var DOC7 = "See docs/next-codebase-guide/rules/redundant-aliases-rule.md";
6814
7206
  function hasTypeAnnotation(identifier) {
6815
7207
  return "typeAnnotation" in identifier && identifier.typeAnnotation !== void 0;
6816
7208
  }
@@ -6822,19 +7214,19 @@ function directPropertyBinding(context, declarator, isEnumValue) {
6822
7214
  if (member.computed || member.optional || member.property.type !== "Identifier") return void 0;
6823
7215
  if (!memberCanBecomeLocal(member)) return void 0;
6824
7216
  if (context.sourceCode.getCommentsInside(declarator).length > 0) return void 0;
6825
- const propertyName5 = member.property.name;
7217
+ const propertyName6 = member.property.name;
6826
7218
  const localName = declarator.id.name;
6827
- if (propertyName5 !== localName) return void 0;
7219
+ if (propertyName6 !== localName) return void 0;
6828
7220
  const source = member.object;
6829
7221
  const sourceText = context.sourceCode.getText(source);
6830
7222
  return {
6831
7223
  declarator,
6832
7224
  member,
6833
- propertyName: propertyName5,
7225
+ propertyName: propertyName6,
6834
7226
  localName,
6835
7227
  source,
6836
7228
  sourceText,
6837
- bindingText: propertyName5
7229
+ bindingText: propertyName6
6838
7230
  };
6839
7231
  }
6840
7232
  function canGroupSource(source) {
@@ -6852,8 +7244,8 @@ function rootIdentifierName(node) {
6852
7244
  if (node.type !== "MemberExpression" || node.object.type === "Super") return void 0;
6853
7245
  return rootIdentifierName(node.object);
6854
7246
  }
6855
- function isCompliantLocalName(propertyName5) {
6856
- return !propertyName5.includes("_") || /^[A-Z][A-Z0-9]*(?:_[A-Z0-9]+)*$/u.test(propertyName5);
7247
+ function isCompliantLocalName(propertyName6) {
7248
+ return !propertyName6.includes("_") || /^[A-Z][A-Z0-9]*(?:_[A-Z0-9]+)*$/u.test(propertyName6);
6857
7249
  }
6858
7250
  function propertyNameOf(node) {
6859
7251
  if (node.type !== "Property" || node.computed) return void 0;
@@ -6902,8 +7294,8 @@ function enumValueResolver(context) {
6902
7294
  const checker = services.program.getTypeChecker();
6903
7295
  const { esTreeNodeToTSNodeMap: nodeMap } = services;
6904
7296
  const isEnumSymbol = (symbol) => {
6905
- const resolved = symbol.flags === ts10.SymbolFlags.Alias ? checker.getAliasedSymbol(symbol) : symbol;
6906
- return (resolved.declarations ?? []).some((declaration) => ts10.isEnumDeclaration(declaration));
7297
+ const resolved = symbol.flags === ts11.SymbolFlags.Alias ? checker.getAliasedSymbol(symbol) : symbol;
7298
+ return (resolved.declarations ?? []).some((declaration) => ts11.isEnumDeclaration(declaration));
6907
7299
  };
6908
7300
  return (node) => {
6909
7301
  const tsNode = nodeMap.get(node);
@@ -6919,27 +7311,27 @@ function detachableCallResolver(context) {
6919
7311
  if (!services) return () => false;
6920
7312
  const checker = services.program.getTypeChecker();
6921
7313
  const { esTreeNodeToTSNodeMap: nodeMap } = services;
6922
- const isUnboundFunctionType = (type) => ts10.isFunctionTypeNode(type) && !type.parameters.some((parameter) => ts10.isIdentifier(parameter.name) && parameter.name.text === "this");
7314
+ const isUnboundFunctionType = (type) => ts11.isFunctionTypeNode(type) && !type.parameters.some((parameter) => ts11.isIdentifier(parameter.name) && parameter.name.text === "this");
6923
7315
  return (member) => {
6924
7316
  const node = nodeMap.get(member);
6925
- if (!node || !ts10.isPropertyAccessExpression(node)) return false;
7317
+ if (!node || !ts11.isPropertyAccessExpression(node)) return false;
6926
7318
  const symbol = checker.getSymbolAtLocation(node.name);
6927
7319
  const declarations = symbol?.declarations;
6928
7320
  if (!declarations?.length) return false;
6929
7321
  return declarations.every((declaration) => {
6930
- if (ts10.isPropertySignature(declaration) || ts10.isPropertyDeclaration(declaration)) {
6931
- return declaration.type !== void 0 && isUnboundFunctionType(declaration.type) || ts10.isPropertyDeclaration(declaration) && declaration.initializer !== void 0 && ts10.isArrowFunction(declaration.initializer);
7322
+ if (ts11.isPropertySignature(declaration) || ts11.isPropertyDeclaration(declaration)) {
7323
+ return declaration.type !== void 0 && isUnboundFunctionType(declaration.type) || ts11.isPropertyDeclaration(declaration) && declaration.initializer !== void 0 && ts11.isArrowFunction(declaration.initializer);
6932
7324
  }
6933
- if (ts10.isPropertyAssignment(declaration)) return ts10.isArrowFunction(declaration.initializer);
7325
+ if (ts11.isPropertyAssignment(declaration)) return ts11.isArrowFunction(declaration.initializer);
6934
7326
  return false;
6935
7327
  });
6936
7328
  };
6937
7329
  }
6938
7330
  function directMappingRequiresQualifiedAccess(context, ownershipResolver, member) {
6939
- const mapping = renamedDirectMapping(context, member);
6940
- if (!mapping || !ownershipResolver) return false;
6941
- const sourceResolution = ownershipResolver.sourceMember(mapping.sourceMember);
6942
- const targetResolution = ownershipResolver.targetProperty(mapping.property, mapping.targetName);
7331
+ const mapping2 = renamedDirectMapping(context, member);
7332
+ if (!mapping2 || !ownershipResolver) return false;
7333
+ const sourceResolution = ownershipResolver.sourceMember(mapping2.sourceMember);
7334
+ const targetResolution = ownershipResolver.targetProperty(mapping2.property, mapping2.targetName);
6943
7335
  return sourceResolution.kind === "data-contract" || targetResolution.kind === "data-contract";
6944
7336
  }
6945
7337
  function memberCanBeDestructured(context, ownershipResolver, member, isEnumValue) {
@@ -6975,10 +7367,10 @@ function recordMemberUsage(context, scope, ownershipResolver, member, isEnumValu
6975
7367
  if (!isGroupedUsageSource(member.object) || !memberIsRead(context, member, detachableCall)) return;
6976
7368
  const sourceText = context.sourceCode.getText(member.object);
6977
7369
  const usage = objectUsage(scope, sourceText);
6978
- const propertyName5 = member.property.name;
6979
- usage.propertyNames.add(propertyName5);
7370
+ const propertyName6 = member.property.name;
7371
+ usage.propertyNames.add(propertyName6);
6980
7372
  if (!memberIsDirectVariableInitializer(context, member)) {
6981
- usage.directMembers.push({ member, propertyName: propertyName5 });
7373
+ usage.directMembers.push({ member, propertyName: propertyName6 });
6982
7374
  }
6983
7375
  }
6984
7376
  function recordDestructuringUsage(context, scope, declaration, isEnumValue) {
@@ -7001,7 +7393,7 @@ function recordDestructuringUsage(context, scope, declaration, isEnumValue) {
7001
7393
  }
7002
7394
  function scopeUsageMessage(sourceText, propertyNames) {
7003
7395
  const names = [...propertyNames].map((name) => `"${name}"`).join(", ");
7004
- return `${names} are read from "${sourceText}" in the same block. Destructure them together in one declaration. ${DOC6}`;
7396
+ return `${names} are read from "${sourceText}" in the same block. Destructure them together in one declaration. ${DOC7}`;
7005
7397
  }
7006
7398
  function hasBinding(context, node, name) {
7007
7399
  const initialScope = context.sourceCode.getScope(node);
@@ -7105,13 +7497,13 @@ function groupedDestructuringSelections(context, first, isEnumValue) {
7105
7497
  if (!previous || nextNode?.type !== "VariableDeclaration" || nextNode.kind !== first.declaration.kind) break;
7106
7498
  const next = destructuringSelection(context, nextNode, isEnumValue);
7107
7499
  if (next?.sourceText !== first.sourceText) break;
7108
- if (next.propertyNames.some((propertyName5) => seenProperties.has(propertyName5))) break;
7500
+ if (next.propertyNames.some((propertyName6) => seenProperties.has(propertyName6))) break;
7109
7501
  const [, previousEnd] = context.sourceCode.getRange(previous);
7110
7502
  const [nextStart] = context.sourceCode.getRange(nextNode);
7111
7503
  const gap = context.sourceCode.text.slice(previousEnd, nextStart);
7112
7504
  if (!whitespaceKeepsStatementsAdjacent(gap)) break;
7113
7505
  group.push(next);
7114
- for (const propertyName5 of next.propertyNames) seenProperties.add(propertyName5);
7506
+ for (const propertyName6 of next.propertyNames) seenProperties.add(propertyName6);
7115
7507
  }
7116
7508
  return group;
7117
7509
  }
@@ -7119,19 +7511,19 @@ function declarationTerminator(context, declaration) {
7119
7511
  return context.sourceCode.getText(declaration).trimEnd().endsWith(";") ? ";" : "";
7120
7512
  }
7121
7513
  function singlePropertyMessage(binding) {
7122
- return `"${binding.propertyName}" is the only property bound from "${binding.sourceText}". Read "${binding.sourceText}.${binding.propertyName}" directly instead of creating a local binding. ${DOC6}`;
7514
+ return `"${binding.propertyName}" is the only property bound from "${binding.sourceText}". Read "${binding.sourceText}.${binding.propertyName}" directly instead of creating a local binding. ${DOC7}`;
7123
7515
  }
7124
7516
  function groupMessage(bindings) {
7125
7517
  const firstBinding = bindings[0];
7126
- if (!firstBinding) return `Use one object destructuring declaration. ${DOC6}`;
7518
+ if (!firstBinding) return `Use one object destructuring declaration. ${DOC7}`;
7127
7519
  const names = bindings.map(({ localName }) => `"${localName}"`).join(", ");
7128
- return `${names} are derived directly from properties of "${firstBinding.sourceText}". Use one object destructuring declaration. ${DOC6}`;
7520
+ return `${names} are derived directly from properties of "${firstBinding.sourceText}". Use one object destructuring declaration. ${DOC7}`;
7129
7521
  }
7130
7522
  function repeatedDestructuringMessage(group) {
7131
7523
  const first = group[0];
7132
- if (!first) return `Combine repeated destructuring into one declaration. ${DOC6}`;
7524
+ if (!first) return `Combine repeated destructuring into one declaration. ${DOC7}`;
7133
7525
  const names = group.flatMap(({ localNames }) => localNames).map((name) => `"${name}"`).join(", ");
7134
- return `${names} destructure the same source "${first.sourceText}" repeatedly. Combine them into one object destructuring declaration. ${DOC6}`;
7526
+ return `${names} destructure the same source "${first.sourceText}" repeatedly. Combine them into one object destructuring declaration. ${DOC7}`;
7135
7527
  }
7136
7528
  var preferObjectDestructuringRule = {
7137
7529
  meta: {
@@ -7165,9 +7557,9 @@ var preferObjectDestructuringRule = {
7165
7557
  const { member: firstDirectMember } = firstDirectUsage;
7166
7558
  const propertyNames = [...usage.propertyNames];
7167
7559
  const missingPropertyNames = propertyNames.filter(
7168
- (propertyName5) => !usage.destructuring?.propertyNames.has(propertyName5)
7560
+ (propertyName6) => !usage.destructuring?.propertyNames.has(propertyName6)
7169
7561
  );
7170
- if (missingPropertyNames.some((propertyName5) => hasBinding(context, firstDirectMember, propertyName5))) {
7562
+ if (missingPropertyNames.some((propertyName6) => hasBinding(context, firstDirectMember, propertyName6))) {
7171
7563
  continue;
7172
7564
  }
7173
7565
  context.report({
@@ -7181,7 +7573,7 @@ var preferObjectDestructuringRule = {
7181
7573
  return null;
7182
7574
  }
7183
7575
  const memberFixes = usage.directMembers.map(
7184
- ({ member, propertyName: propertyName5 }) => fixer.replaceText(member, propertyName5)
7576
+ ({ member, propertyName: propertyName6 }) => fixer.replaceText(member, propertyName6)
7185
7577
  );
7186
7578
  if (usage.destructuring) {
7187
7579
  if (missingPropertyNames.length === 0) return memberFixes;
@@ -7220,7 +7612,7 @@ ${indentation}`;
7220
7612
  continue;
7221
7613
  }
7222
7614
  if (fromSameSource.length > 1) {
7223
- const names = new Set(fromSameSource.map(({ propertyName: propertyName5 }) => propertyName5));
7615
+ const names = new Set(fromSameSource.map(({ propertyName: propertyName6 }) => propertyName6));
7224
7616
  if (names.size > 1) {
7225
7617
  context.report({ node: binding.node, message: scopeUsageMessage(binding.sourceText, names) });
7226
7618
  continue;
@@ -7249,7 +7641,7 @@ ${indentation}`;
7249
7641
  const sourceText = context.sourceCode.getText(declarator.init);
7250
7642
  context.report({
7251
7643
  node: declarator.id,
7252
- message: `"${sourceText}" is an enum. Keep enum member accesses qualified instead of destructuring it. ${DOC6}`
7644
+ message: `"${sourceText}" is an enum. Keep enum member accesses qualified instead of destructuring it. ${DOC7}`
7253
7645
  });
7254
7646
  }
7255
7647
  recordDestructuringUsage(context, currentUsageScope(), node, isEnumValue);
@@ -7260,12 +7652,12 @@ ${indentation}`;
7260
7652
  if (group.length <= 1) {
7261
7653
  if (node.kind === "const" && selection.propertyNames.length === 1 && supportsSinglePropertySource(selection.source)) {
7262
7654
  const declarator = node.declarations[0];
7263
- const propertyName5 = selection.propertyNames[0];
7264
- if (declarator && propertyName5) {
7655
+ const propertyName6 = selection.propertyNames[0];
7656
+ if (declarator && propertyName6) {
7265
7657
  currentUsageScope()?.singleProperties.push({
7266
7658
  node: declarator.id,
7267
7659
  sourceText: selection.sourceText,
7268
- propertyName: propertyName5
7660
+ propertyName: propertyName6
7269
7661
  });
7270
7662
  }
7271
7663
  }
@@ -7295,7 +7687,7 @@ ${indentation}`;
7295
7687
  if (bindings.length === 0) return;
7296
7688
  const firstBinding = bindings[0];
7297
7689
  if (!firstBinding) return;
7298
- const sameSourceBindings = bindings.length > 1 && bindings.length === node.declarations.length && bindings.every(({ sourceText }) => sourceText === firstBinding.sourceText) && new Set(bindings.map(({ propertyName: propertyName5 }) => propertyName5)).size === bindings.length;
7690
+ const sameSourceBindings = bindings.length > 1 && bindings.length === node.declarations.length && bindings.every(({ sourceText }) => sourceText === firstBinding.sourceText) && new Set(bindings.map(({ propertyName: propertyName6 }) => propertyName6)).size === bindings.length;
7299
7691
  if (sameSourceBindings) {
7300
7692
  context.report({
7301
7693
  node,
@@ -7350,7 +7742,7 @@ ${indentation}`;
7350
7742
  };
7351
7743
 
7352
7744
  // eslint/rules/pure-function-extract.ts
7353
- import path47 from "path";
7745
+ import path49 from "path";
7354
7746
  var ROUTE_HANDLER_EXPORT_NAMES = /* @__PURE__ */ new Set([
7355
7747
  "GET",
7356
7748
  "POST",
@@ -7415,12 +7807,12 @@ var pureFunctionExtractRule = {
7415
7807
  },
7416
7808
  create(context) {
7417
7809
  const filename = context.filename;
7418
- const isRouteFile = path47.basename(filename) === "route.ts";
7810
+ const isRouteFile = path49.basename(filename) === "route.ts";
7419
7811
  const isComponentFile = filename.endsWith(".tsx") || filename.endsWith(".jsx");
7420
7812
  const sourceRoot = sourceRootOf(context);
7421
- const relative = path47.relative(sourceRoot, filename);
7813
+ const relative = path49.relative(sourceRoot, filename);
7422
7814
  if (relative.startsWith("..")) return {};
7423
- const segments = relative.split(path47.sep);
7815
+ const segments = relative.split(path49.sep);
7424
7816
  const folders = segments.slice(0, -1);
7425
7817
  const isHookSupportFile = folders.includes("hooks") && /\.(?:[cm]?[jt]s)$/.test(filename);
7426
7818
  if (!isComponentFile && !isRouteFile && !isHookSupportFile) return {};
@@ -7480,15 +7872,15 @@ var pureFunctionExtractRule = {
7480
7872
  };
7481
7873
 
7482
7874
  // eslint/rules/repeated-numeric-value.ts
7483
- import path48 from "path";
7875
+ import path50 from "path";
7484
7876
  function isNonProductionFile(file, sourceRoot) {
7485
- const relative = path48.relative(sourceRoot, file);
7486
- const segments = relative.split(path48.sep);
7487
- const basename = path48.basename(file);
7877
+ const relative = path50.relative(sourceRoot, file);
7878
+ const segments = relative.split(path50.sep);
7879
+ const basename = path50.basename(file);
7488
7880
  return /\.(?:test|spec|mock)\.[^.]+$/.test(basename) || segments.some((segment) => segment === "__tests__" || segment === "__mocks__" || segment === "mocks");
7489
7881
  }
7490
7882
  function isCanonicalConstantFile(file, sourceRoot) {
7491
- const segments = path48.relative(sourceRoot, file).split(path48.sep);
7883
+ const segments = path50.relative(sourceRoot, file).split(path50.sep);
7492
7884
  return segments.includes("constants") || segments[0] === "config";
7493
7885
  }
7494
7886
  function groupKey(literal) {
@@ -7504,7 +7896,7 @@ var repeatedNumericValueRule = {
7504
7896
  },
7505
7897
  create(context) {
7506
7898
  const sourceRoot = sourceRootOf(context);
7507
- const file = path48.resolve(context.filename);
7899
+ const file = path50.resolve(context.filename);
7508
7900
  if (isNonProductionFile(file, sourceRoot) || isCanonicalConstantFile(file, sourceRoot)) return {};
7509
7901
  const index = getProjectIndex(sourceRoot);
7510
7902
  if (!index) return {};
@@ -7541,11 +7933,11 @@ var repeatedNumericValueRule = {
7541
7933
  };
7542
7934
 
7543
7935
  // eslint/rules/repeated-semantic-literal.ts
7544
- import path50 from "path";
7936
+ import path52 from "path";
7545
7937
 
7546
7938
  // eslint/rules/imported-enum-literals.ts
7547
- import path49 from "path";
7548
- import ts11 from "typescript";
7939
+ import path51 from "path";
7940
+ import ts12 from "typescript";
7549
7941
  var columnMethods2 = /* @__PURE__ */ new Set([
7550
7942
  "eq",
7551
7943
  "neq",
@@ -7561,13 +7953,13 @@ var columnMethods2 = /* @__PURE__ */ new Set([
7561
7953
  "filter",
7562
7954
  "not"
7563
7955
  ]);
7564
- function memberName6(name) {
7565
- if (ts11.isIdentifier(name) || ts11.isStringLiteral(name)) return name.text;
7956
+ function memberName7(name) {
7957
+ if (ts12.isIdentifier(name) || ts12.isStringLiteral(name)) return name.text;
7566
7958
  return void 0;
7567
7959
  }
7568
7960
  function isWithin3(root, file) {
7569
- const relative = path49.relative(root, file);
7570
- return relative === "" || !relative.startsWith("..") && !path49.isAbsolute(relative);
7961
+ const relative = path51.relative(root, file);
7962
+ return relative === "" || !relative.startsWith("..") && !path51.isAbsolute(relative);
7571
7963
  }
7572
7964
  function domainOf(name) {
7573
7965
  if (name.endsWith("ColumnEnum")) return "column";
@@ -7577,23 +7969,23 @@ function domainOf(name) {
7577
7969
  function importedEnums(file, checker, sourceRoot, importedNames) {
7578
7970
  const matches = /* @__PURE__ */ new Map();
7579
7971
  for (const statement of file.statements) {
7580
- if (!ts11.isImportDeclaration(statement) || !statement.importClause?.namedBindings || !ts11.isNamedImports(statement.importClause.namedBindings)) {
7972
+ if (!ts12.isImportDeclaration(statement) || !statement.importClause?.namedBindings || !ts12.isNamedImports(statement.importClause.namedBindings)) {
7581
7973
  continue;
7582
7974
  }
7583
7975
  for (const specifier of statement.importClause.namedBindings.elements) {
7584
7976
  if (!importedNames.has(specifier.name.text)) continue;
7585
7977
  const symbol = checker.getSymbolAtLocation(specifier.name);
7586
7978
  if (!symbol) continue;
7587
- const resolved = symbol.flags === ts11.SymbolFlags.Alias ? checker.getAliasedSymbol(symbol) : symbol;
7979
+ const resolved = symbol.flags === ts12.SymbolFlags.Alias ? checker.getAliasedSymbol(symbol) : symbol;
7588
7980
  for (const declaration of resolved.declarations ?? []) {
7589
- if (!ts11.isEnumDeclaration(declaration)) continue;
7590
- const declarationFile = path49.resolve(declaration.getSourceFile().fileName);
7981
+ if (!ts12.isEnumDeclaration(declaration)) continue;
7982
+ const declarationFile = path51.resolve(declaration.getSourceFile().fileName);
7591
7983
  if (!isWithin3(sourceRoot, declarationFile)) continue;
7592
7984
  const domain = domainOf(declaration.name.text);
7593
7985
  if (!domain) continue;
7594
7986
  for (const member of declaration.members) {
7595
- if (!member.initializer || !ts11.isStringLiteral(member.initializer)) continue;
7596
- const name = memberName6(member.name);
7987
+ if (!member.initializer || !ts12.isStringLiteral(member.initializer)) continue;
7988
+ const name = memberName7(member.name);
7597
7989
  if (!name) continue;
7598
7990
  const entries = matches.get(member.initializer.text) ?? [];
7599
7991
  entries.push({
@@ -7609,25 +8001,25 @@ function importedEnums(file, checker, sourceRoot, importedNames) {
7609
8001
  return matches;
7610
8002
  }
7611
8003
  function isPathname2(node) {
7612
- return ts11.isPropertyAccessExpression(node) && node.name.text === "pathname";
8004
+ return ts12.isPropertyAccessExpression(node) && node.name.text === "pathname";
7613
8005
  }
7614
8006
  function domainForUse(node) {
7615
8007
  const parent = node.parent;
7616
- if (ts11.isPropertyAssignment(parent) && parent.initializer === node && memberName6(parent.name) === "path") {
8008
+ if (ts12.isPropertyAssignment(parent) && parent.initializer === node && memberName7(parent.name) === "path") {
7617
8009
  return "route";
7618
8010
  }
7619
- if (ts11.isCallExpression(parent) && parent.arguments[0] === node && ts11.isPropertyAccessExpression(parent.expression)) {
8011
+ if (ts12.isCallExpression(parent) && parent.arguments[0] === node && ts12.isPropertyAccessExpression(parent.expression)) {
7620
8012
  const { expression, name } = parent.expression;
7621
8013
  if (columnMethods2.has(name.text)) return "column";
7622
8014
  if (name.text === "startsWith" && isPathname2(expression)) return "route";
7623
8015
  }
7624
- if (ts11.isBinaryExpression(parent) && (parent.operatorToken.kind === ts11.SyntaxKind.EqualsEqualsEqualsToken || parent.operatorToken.kind === ts11.SyntaxKind.ExclamationEqualsEqualsToken) && (parent.left === node && isPathname2(parent.right) || parent.right === node && isPathname2(parent.left))) {
8016
+ if (ts12.isBinaryExpression(parent) && (parent.operatorToken.kind === ts12.SyntaxKind.EqualsEqualsEqualsToken || parent.operatorToken.kind === ts12.SyntaxKind.ExclamationEqualsEqualsToken) && (parent.left === node && isPathname2(parent.right) || parent.right === node && isPathname2(parent.left))) {
7625
8017
  return "route";
7626
8018
  }
7627
8019
  return void 0;
7628
8020
  }
7629
8021
  function importedEnumLiteralUses(context, root) {
7630
- const filename = path49.resolve(context.filename);
8022
+ const filename = path51.resolve(context.filename);
7631
8023
  if (!isWithin3(root, filename)) return [];
7632
8024
  const services = typedParserServices(context.sourceCode.parserServices);
7633
8025
  if (!services) return [];
@@ -7643,7 +8035,7 @@ function importedEnumLiteralUses(context, root) {
7643
8035
  if (matches.size === 0) return [];
7644
8036
  const uses = [];
7645
8037
  const visit = (node) => {
7646
- if (ts11.isStringLiteral(node)) {
8038
+ if (ts12.isStringLiteral(node)) {
7647
8039
  const domain = domainForUse(node);
7648
8040
  const candidates = matches.get(node.text)?.filter((entry) => entry.domain === domain) ?? [];
7649
8041
  if (candidates.length === 1) {
@@ -7660,14 +8052,14 @@ function importedEnumLiteralUses(context, root) {
7660
8052
  }
7661
8053
  }
7662
8054
  }
7663
- ts11.forEachChild(node, visit);
8055
+ ts12.forEachChild(node, visit);
7664
8056
  };
7665
8057
  visit(file);
7666
8058
  return uses;
7667
8059
  }
7668
8060
 
7669
8061
  // eslint/rules/repeated-semantic-literal.ts
7670
- var DOC7 = "See docs/next-codebase-guide/rules/constants-rule.md";
8062
+ var DOC8 = "See docs/next-codebase-guide/rules/constants-rule.md";
7671
8063
  var closedDomainFamilies = /* @__PURE__ */ new Set(["api-route", "event", "storage"]);
7672
8064
  function canonicalMatches(use, canonical, sourceRoot) {
7673
8065
  if (use.kind !== canonical.kind || use.value !== canonical.value) return false;
@@ -7681,7 +8073,7 @@ function canonicalMatches(use, canonical, sourceRoot) {
7681
8073
  const semanticName2 = use.family.split(":")[1];
7682
8074
  if (!semanticName2 || !name.toLowerCase().includes(semanticName2.toLowerCase())) return false;
7683
8075
  const location = featureOf(canonical.file, sourceRoot);
7684
- return location === featureOf(use.file, sourceRoot) || path50.relative(sourceRoot, canonical.file).split(path50.sep)[0] === "constants";
8076
+ return location === featureOf(use.file, sourceRoot) || path52.relative(sourceRoot, canonical.file).split(path52.sep)[0] === "constants";
7685
8077
  }
7686
8078
  return false;
7687
8079
  }
@@ -7695,14 +8087,14 @@ function messageFor(use, matches, duplicateRouteDomains, existingRouteEnum, root
7695
8087
  const count = new Set(matches.map((match) => match.file)).size;
7696
8088
  const kind = use.kind === "string" ? "string" : "numeric";
7697
8089
  if (use.family === "api-route" && existingRouteEnum?.owner) {
7698
- const location = path50.relative(root, existingRouteEnum.file).replaceAll(path50.sep, "/");
7699
- return `The route ${formatValue(use)} repeats; add a member to existing ${existingRouteEnum.owner} in src/${location} and reuse it. ${DOC7}`;
8090
+ const location = path52.relative(root, existingRouteEnum.file).replaceAll(path52.sep, "/");
8091
+ return `The route ${formatValue(use)} repeats; add a member to existing ${existingRouteEnum.owner} in src/${location} and reuse it. ${DOC8}`;
7700
8092
  }
7701
8093
  if (count === 1) {
7702
- return `The ${kind} literal ${formatValue(use)} repeats in the same semantic role in this file. Extract a file-local const. ${DOC7}`;
8094
+ return `The ${kind} literal ${formatValue(use)} repeats in the same semantic role in this file. Extract a file-local const. ${DOC8}`;
7703
8095
  }
7704
8096
  const placement = use.family === "api-route" && duplicateRouteDomains.has(use.role) ? "a shared enum for this closed route domain" : "one shared const";
7705
- return `The ${kind} literal ${formatValue(use)} repeats in ${String(count)} production files for the same semantic role. Extract ${placement} at the consumers' CCF and import it. ${DOC7}`;
8097
+ return `The ${kind} literal ${formatValue(use)} repeats in ${String(count)} production files for the same semantic role. Extract ${placement} at the consumers' CCF and import it. ${DOC8}`;
7706
8098
  }
7707
8099
  var repeatedSemanticLiteralRule = {
7708
8100
  meta: {
@@ -7714,7 +8106,7 @@ var repeatedSemanticLiteralRule = {
7714
8106
  },
7715
8107
  create(context) {
7716
8108
  const root = sourceRootOf(context);
7717
- const file = path50.resolve(context.filename);
8109
+ const file = path52.resolve(context.filename);
7718
8110
  if (!isProductionSource(file, root)) return {};
7719
8111
  const project = getProjectIndex(root);
7720
8112
  if (!project?.modules.has(file)) return {};
@@ -7759,11 +8151,11 @@ var repeatedSemanticLiteralRule = {
7759
8151
  return {
7760
8152
  Program(node) {
7761
8153
  for (const use of imported) {
7762
- const relative = path50.relative(root, use.sourceFile).replaceAll(path50.sep, "/");
8154
+ const relative = path52.relative(root, use.sourceFile).replaceAll(path52.sep, "/");
7763
8155
  context.report({
7764
8156
  node,
7765
8157
  loc: { line: use.line, column: use.column },
7766
- message: `Reuse ${use.reference} from src/${relative} instead of raw ${JSON.stringify(use.value)}. ${DOC7}`
8158
+ message: `Reuse ${use.reference} from src/${relative} instead of raw ${JSON.stringify(use.value)}. ${DOC8}`
7767
8159
  });
7768
8160
  }
7769
8161
  for (const use of current) {
@@ -7774,11 +8166,11 @@ var repeatedSemanticLiteralRule = {
7774
8166
  if (candidates.length === 1) {
7775
8167
  const canonical = candidates[0];
7776
8168
  if (!canonical) continue;
7777
- const relative = path50.relative(root, canonical.file).replaceAll(path50.sep, "/");
8169
+ const relative = path52.relative(root, canonical.file).replaceAll(path52.sep, "/");
7778
8170
  context.report({
7779
8171
  node,
7780
8172
  loc: { line: use.line, column: use.column },
7781
- message: `Reuse ${canonicalName(canonical)} from src/${relative} instead of raw ${formatValue(use)}. ${DOC7}`
8173
+ message: `Reuse ${canonicalName(canonical)} from src/${relative} instead of raw ${formatValue(use)}. ${DOC8}`
7782
8174
  });
7783
8175
  continue;
7784
8176
  }
@@ -7787,11 +8179,11 @@ var repeatedSemanticLiteralRule = {
7787
8179
  const peers = groups.get(key) ?? [];
7788
8180
  if (peers.length < 2) {
7789
8181
  if (use.family === "api-route" && existingRouteEnum?.owner) {
7790
- const location = path50.relative(root, existingRouteEnum.file).replaceAll(path50.sep, "/");
8182
+ const location = path52.relative(root, existingRouteEnum.file).replaceAll(path52.sep, "/");
7791
8183
  context.report({
7792
8184
  node,
7793
8185
  loc: { line: use.line, column: use.column },
7794
- message: `The route ${formatValue(use)} belongs to existing ${existingRouteEnum.owner}; add a member in src/${location} and reuse it. ${DOC7}`
8186
+ message: `The route ${formatValue(use)} belongs to existing ${existingRouteEnum.owner}; add a member in src/${location} and reuse it. ${DOC8}`
7795
8187
  });
7796
8188
  continue;
7797
8189
  }
@@ -7800,7 +8192,7 @@ var repeatedSemanticLiteralRule = {
7800
8192
  context.report({
7801
8193
  node,
7802
8194
  loc: { line: use.line, column: use.column },
7803
- message: `The string literal ${formatValue(use)} is one of ${String(domain.size)} values in a closed ${use.family} domain. Declare the domain in a shared enum at the consumers' CCF and reuse it. ${DOC7}`
8195
+ message: `The string literal ${formatValue(use)} is one of ${String(domain.size)} values in a closed ${use.family} domain. Declare the domain in a shared enum at the consumers' CCF and reuse it. ${DOC8}`
7804
8196
  });
7805
8197
  }
7806
8198
  continue;
@@ -7999,7 +8391,7 @@ var repeatedStructureRule = {
7999
8391
 
8000
8392
  // eslint/rules/require-barrel-star-exports.ts
8001
8393
  import fs5 from "fs";
8002
- import path51 from "path";
8394
+ import path53 from "path";
8003
8395
  var SUPPORT_FOLDERS3 = /* @__PURE__ */ new Set(["constants", "types", "schemas"]);
8004
8396
  var INDEX_NAMES = /* @__PURE__ */ new Set(["index.ts", "index.tsx", "index.mts", "index.cts"]);
8005
8397
  var MODULE_EXTENSIONS3 = [".ts", ".tsx", ".mts", ".cts", ".js", ".jsx", ".mjs", ".cjs"];
@@ -8007,9 +8399,9 @@ function resolveSiblingModule(indexFile, specifier) {
8007
8399
  if (!specifier.startsWith("./")) return void 0;
8008
8400
  const relative = specifier.slice(2);
8009
8401
  if (!relative || relative.includes("/")) return void 0;
8010
- const directory = path51.dirname(indexFile);
8011
- const direct = path51.resolve(directory, relative);
8012
- const candidates = path51.extname(direct) ? [direct] : MODULE_EXTENSIONS3.map((extension) => `${direct}${extension}`);
8402
+ const directory = path53.dirname(indexFile);
8403
+ const direct = path53.resolve(directory, relative);
8404
+ const candidates = path53.extname(direct) ? [direct] : MODULE_EXTENSIONS3.map((extension) => `${direct}${extension}`);
8013
8405
  return candidates.find((candidate) => fs5.existsSync(candidate) && fs5.statSync(candidate).isFile());
8014
8406
  }
8015
8407
  var requireBarrelStarExportsRule = {
@@ -8022,9 +8414,9 @@ var requireBarrelStarExportsRule = {
8022
8414
  fixable: "code"
8023
8415
  },
8024
8416
  create(context) {
8025
- const filename = path51.resolve(context.filename);
8026
- if (!INDEX_NAMES.has(path51.basename(filename))) return {};
8027
- if (!SUPPORT_FOLDERS3.has(path51.basename(path51.dirname(filename)))) return {};
8417
+ const filename = path53.resolve(context.filename);
8418
+ if (!INDEX_NAMES.has(path53.basename(filename))) return {};
8419
+ if (!SUPPORT_FOLDERS3.has(path53.basename(path53.dirname(filename)))) return {};
8028
8420
  return {
8029
8421
  ExportNamedDeclaration(node) {
8030
8422
  const sourceNode = node.source;
@@ -8077,7 +8469,7 @@ var requireBarrelStarExportsRule = {
8077
8469
  };
8078
8470
 
8079
8471
  // eslint/rules/root-support-placement.ts
8080
- import path52 from "path";
8472
+ import path54 from "path";
8081
8473
  function isSupportFolder(value) {
8082
8474
  return value === "utils" || value === "types" || value === "schemas" || value === "constants";
8083
8475
  }
@@ -8110,7 +8502,7 @@ var rootSupportPlacementRule = {
8110
8502
  },
8111
8503
  create(context) {
8112
8504
  const sourceRoot = sourceRootOf(context);
8113
- const file = path52.resolve(context.filename);
8505
+ const file = path54.resolve(context.filename);
8114
8506
  const segments = segmentsOf(file, sourceRoot);
8115
8507
  const folderSegments = folderSegmentsOf(file, sourceRoot);
8116
8508
  const supportFolder = folderSegments[folderSegments.length - 1];
@@ -8156,8 +8548,104 @@ var rootSupportPlacementRule = {
8156
8548
  };
8157
8549
 
8158
8550
  // eslint/rules/route-handler-shape.ts
8159
- import path53 from "path";
8160
- import ts12 from "typescript";
8551
+ import path56 from "path";
8552
+ import ts13 from "typescript";
8553
+
8554
+ // eslint/rules/route-single-use-delegation.ts
8555
+ import path55 from "path";
8556
+ function responseCall(expression) {
8557
+ if (!expression) return void 0;
8558
+ if (expression.type === "AwaitExpression") return responseCall(expression.argument);
8559
+ if (expression.type === "CallExpression" && expression.callee.type === "Identifier") return expression;
8560
+ if (expression.type !== "ObjectExpression") return void 0;
8561
+ const dataProperties = expression.properties.filter(
8562
+ (property) => property.type === "Property" && !property.computed && (property.key.type === "Identifier" && property.key.name === "data" || property.key.type === "Literal" && property.key.value === "data")
8563
+ );
8564
+ if (dataProperties.length !== 1) return void 0;
8565
+ const otherProperties = expression.properties.filter((property) => !dataProperties.includes(property));
8566
+ if (otherProperties.some(
8567
+ (property) => property.type !== "Property" || property.value.type !== "Literal" || property.computed
8568
+ )) {
8569
+ return void 0;
8570
+ }
8571
+ return responseCall(dataProperties[0]?.type === "Property" ? dataProperties[0].value : void 0);
8572
+ }
8573
+ function soleDelegation(handler) {
8574
+ if (handler.body.type !== "BlockStatement") return responseCall(handler.body);
8575
+ const statements = handler.body.body;
8576
+ if (statements.length === 1 && statements[0]?.type === "ReturnStatement") {
8577
+ return responseCall(statements[0].argument);
8578
+ }
8579
+ const [declaration, returned] = statements;
8580
+ if (statements.length !== 2 || declaration?.type !== "VariableDeclaration" || declaration.declarations.length !== 1 || returned?.type !== "ReturnStatement") {
8581
+ return void 0;
8582
+ }
8583
+ const variable = declaration.declarations[0];
8584
+ if (variable?.id.type !== "Identifier") return void 0;
8585
+ const call = responseCall(variable.init);
8586
+ if (!call || !returned.argument) return void 0;
8587
+ if (returned.argument.type === "Identifier" && returned.argument.name === variable.id.name) return call;
8588
+ if (returned.argument.type !== "ObjectExpression") return void 0;
8589
+ const properties = returned.argument.properties;
8590
+ if (properties.length !== 1 || properties[0]?.type !== "Property") return void 0;
8591
+ const property = properties[0];
8592
+ const key = property.key;
8593
+ const isData = !property.computed && (key.type === "Identifier" && key.name === "data" || key.type === "Literal" && key.value === "data");
8594
+ return isData && property.value.type === "Identifier" && property.value.name === variable.id.name ? call : void 0;
8595
+ }
8596
+ function isTestFile2(file) {
8597
+ return /(?:\.test|\.spec)\.[cm]?[jt]sx?$/.test(file) || path55.normalize(file).split(path55.sep).includes("__tests__");
8598
+ }
8599
+ function functionSource(index, file, name, sourceRoot, visited = /* @__PURE__ */ new Set()) {
8600
+ if (visited.has(file)) return void 0;
8601
+ visited.add(file);
8602
+ const module = index.modules.get(file);
8603
+ if (!module) return void 0;
8604
+ if (module.exports.some((entry) => entry.name === name && entry.kind === "function")) return file;
8605
+ if (!module.exports.some((entry) => entry.name === name) && !module.reexports.some((entry) => entry.names.length === 0)) {
8606
+ return void 0;
8607
+ }
8608
+ for (const entry of module.reexports) {
8609
+ if (entry.names.length > 0 && !entry.names.includes(name)) continue;
8610
+ const target = resolveSpecifier(file, entry.specifier, sourceRoot);
8611
+ if (!target) continue;
8612
+ const original = functionSource(index, target, name, sourceRoot, visited);
8613
+ if (original) return original;
8614
+ }
8615
+ return void 0;
8616
+ }
8617
+ function singleUseResponseDelegate(context, handler) {
8618
+ const call = soleDelegation(handler);
8619
+ if (call?.callee.type !== "Identifier") return void 0;
8620
+ const name = call.callee.name;
8621
+ const sourceRoot = sourceRootOf(context);
8622
+ const index = getProjectIndex(sourceRoot);
8623
+ if (!index) return void 0;
8624
+ for (const statement of context.sourceCode.ast.body) {
8625
+ if (statement.type !== "ImportDeclaration" || typeof statement.source.value !== "string") continue;
8626
+ const target = resolveSpecifier(context.filename, statement.source.value, sourceRoot);
8627
+ if (target === void 0 || target === context.filename) continue;
8628
+ for (const specifier of statement.specifiers) {
8629
+ if (specifier.type !== "ImportSpecifier" || specifier.local.name !== name) continue;
8630
+ const original = specifier.imported.type === "Identifier" ? specifier.imported.name : String(specifier.imported.value);
8631
+ const source = functionSource(index, target, original, sourceRoot);
8632
+ if (!source) continue;
8633
+ const bindings = context.sourceCode.getDeclaredVariables(specifier);
8634
+ if (!bindings.some((binding) => binding.references.length === 1)) continue;
8635
+ const consumers = index.symbolConsumers.get(symbolKey(source, original));
8636
+ if (!consumers?.has(context.filename)) continue;
8637
+ const activeConsumers = [...consumers].filter((consumer) => {
8638
+ if (isTestFile2(consumer)) return false;
8639
+ const module = index.modules.get(consumer);
8640
+ return !(module && module.reexports.length > 0 && module.imports.length === module.reexports.length && module.exports.every((entry) => entry.kind === "other"));
8641
+ });
8642
+ if (activeConsumers.length === 1 && activeConsumers[0] === context.filename) return original;
8643
+ }
8644
+ }
8645
+ return void 0;
8646
+ }
8647
+
8648
+ // eslint/rules/route-handler-shape.ts
8161
8649
  var HTTP_METHODS2 = /* @__PURE__ */ new Set(["GET", "POST", "PUT", "PATCH", "DELETE", "HEAD", "OPTIONS"]);
8162
8650
  var REQUIRED_BOUNDARY = "withResponse";
8163
8651
  function isFunctionLike(node) {
@@ -8175,33 +8663,33 @@ function findHandler(node) {
8175
8663
  return void 0;
8176
8664
  }
8177
8665
  function isLoop(node) {
8178
- return ts12.isForStatement(node) || ts12.isForOfStatement(node) || ts12.isForInStatement(node) || ts12.isWhileStatement(node) || ts12.isDoStatement(node);
8666
+ return ts13.isForStatement(node) || ts13.isForOfStatement(node) || ts13.isForInStatement(node) || ts13.isWhileStatement(node) || ts13.isDoStatement(node);
8179
8667
  }
8180
8668
  function isFunctionBoundary(node) {
8181
- return ts12.isFunctionExpression(node) || ts12.isArrowFunction(node) || ts12.isFunctionDeclaration(node);
8669
+ return ts13.isFunctionExpression(node) || ts13.isArrowFunction(node) || ts13.isFunctionDeclaration(node);
8182
8670
  }
8183
8671
  function analyzeHandlerBody(body, sourceText) {
8184
8672
  const start = body.range?.[0] ?? 0;
8185
8673
  const end = body.range?.[1] ?? sourceText.length;
8186
- const sourceFile = ts12.createSourceFile(
8674
+ const sourceFile = ts13.createSourceFile(
8187
8675
  "route.ts",
8188
8676
  sourceText.slice(start, end),
8189
- ts12.ScriptTarget.Latest,
8677
+ ts13.ScriptTarget.Latest,
8190
8678
  true,
8191
- ts12.ScriptKind.TS
8679
+ ts13.ScriptKind.TS
8192
8680
  );
8193
8681
  const kinds = /* @__PURE__ */ new Set();
8194
8682
  const calledNames = /* @__PURE__ */ new Set();
8195
8683
  const visit = (node) => {
8196
- if (ts12.isTryStatement(node)) kinds.add("try");
8684
+ if (ts13.isTryStatement(node)) kinds.add("try");
8197
8685
  if (isLoop(node)) kinds.add("loop");
8198
- if (ts12.isIfStatement(node)) kinds.add("if");
8199
- if (ts12.isCallExpression(node) && ts12.isPropertyAccessExpression(node.expression) && node.expression.name.text === "map") {
8686
+ if (ts13.isIfStatement(node)) kinds.add("if");
8687
+ if (ts13.isCallExpression(node) && ts13.isPropertyAccessExpression(node.expression) && node.expression.name.text === "map") {
8200
8688
  kinds.add("map");
8201
8689
  }
8202
- if (ts12.isCallExpression(node) && ts12.isIdentifier(node.expression)) calledNames.add(node.expression.text);
8690
+ if (ts13.isCallExpression(node) && ts13.isIdentifier(node.expression)) calledNames.add(node.expression.text);
8203
8691
  if (isFunctionBoundary(node)) return;
8204
- ts12.forEachChild(node, visit);
8692
+ ts13.forEachChild(node, visit);
8205
8693
  };
8206
8694
  visit(sourceFile);
8207
8695
  return { kinds, calledNames };
@@ -8241,7 +8729,7 @@ var routeHandlerShapeRule = {
8241
8729
  }
8242
8730
  },
8243
8731
  create(context) {
8244
- if (path53.basename(context.filename) !== "route.ts") return {};
8732
+ if (path56.basename(context.filename) !== "route.ts") return {};
8245
8733
  const sourceText = context.sourceCode.text;
8246
8734
  function reportUnwrapped(node, name) {
8247
8735
  context.report({
@@ -8264,6 +8752,13 @@ var routeHandlerShapeRule = {
8264
8752
  });
8265
8753
  return;
8266
8754
  }
8755
+ const singleUseDelegate = singleUseResponseDelegate(context, handler);
8756
+ if (singleUseDelegate) {
8757
+ context.report({
8758
+ node,
8759
+ message: `Handler "${name}" delegates its entire response to single-use utility "${singleUseDelegate}"; inline its workflow in route.ts. See docs/next-codebase-guide/rules/route-handler-rule.md`
8760
+ });
8761
+ }
8267
8762
  const { kinds, calledNames } = analyzeHandlerBody(handler.body, sourceText);
8268
8763
  for (const kind of kinds) {
8269
8764
  context.report({
@@ -8300,7 +8795,7 @@ var routeHandlerShapeRule = {
8300
8795
  };
8301
8796
 
8302
8797
  // eslint/rules/schema-casing.ts
8303
- import path54 from "path";
8798
+ import path57 from "path";
8304
8799
  function isCamelCase(name) {
8305
8800
  return /^[a-z][a-zA-Z0-9]*$/.test(name);
8306
8801
  }
@@ -8328,9 +8823,9 @@ var schemaCasingRule = {
8328
8823
  }
8329
8824
  },
8330
8825
  create(context) {
8331
- const filename = path54.resolve(context.filename);
8826
+ const filename = path57.resolve(context.filename);
8332
8827
  const sourceRoot = sourceRootOf(context);
8333
- if (!filename.startsWith(sourceRoot + path54.sep)) return {};
8828
+ if (!filename.startsWith(sourceRoot + path57.sep)) return {};
8334
8829
  let zodLocalName;
8335
8830
  return {
8336
8831
  ImportDeclaration(node) {
@@ -8362,39 +8857,39 @@ var schemaCasingRule = {
8362
8857
  };
8363
8858
 
8364
8859
  // eslint/rules/sole-state-owner.ts
8365
- import path55 from "path";
8366
- import ts13 from "typescript";
8860
+ import path58 from "path";
8861
+ import ts14 from "typescript";
8367
8862
  function findStateHooks(node) {
8368
8863
  const hooks = [];
8369
8864
  const visit = (child) => {
8370
- if (ts13.isCallExpression(child) && ts13.isIdentifier(child.expression) && child.expression.text === "useState") {
8371
- if (ts13.isVariableDeclaration(child.parent)) {
8865
+ if (ts14.isCallExpression(child) && ts14.isIdentifier(child.expression) && child.expression.text === "useState") {
8866
+ if (ts14.isVariableDeclaration(child.parent)) {
8372
8867
  const { name } = child.parent;
8373
- if (ts13.isArrayBindingPattern(name) && name.elements.length >= 2) {
8868
+ if (ts14.isArrayBindingPattern(name) && name.elements.length >= 2) {
8374
8869
  const value = name.elements[0];
8375
8870
  const updater = name.elements[1];
8376
- if (value && updater && ts13.isBindingElement(value) && ts13.isBindingElement(updater)) {
8871
+ if (value && updater && ts14.isBindingElement(value) && ts14.isBindingElement(updater)) {
8377
8872
  const valueName = value.name;
8378
8873
  const updaterName = updater.name;
8379
- if (ts13.isIdentifier(valueName) && ts13.isIdentifier(updaterName)) {
8874
+ if (ts14.isIdentifier(valueName) && ts14.isIdentifier(updaterName)) {
8380
8875
  hooks.push({ value: valueName.text, updater: updaterName.text });
8381
8876
  }
8382
8877
  }
8383
8878
  }
8384
8879
  }
8385
8880
  }
8386
- ts13.forEachChild(child, visit);
8881
+ ts14.forEachChild(child, visit);
8387
8882
  };
8388
8883
  visit(node);
8389
8884
  return hooks;
8390
8885
  }
8391
8886
  function isHookUsage(node, hook) {
8392
- if (ts13.isCallExpression(node) && ts13.isIdentifier(node.expression) && node.expression.text === hook.updater) {
8887
+ if (ts14.isCallExpression(node) && ts14.isIdentifier(node.expression) && node.expression.text === hook.updater) {
8393
8888
  return "updater";
8394
8889
  }
8395
- if (ts13.isIdentifier(node) && node.text === hook.value) {
8890
+ if (ts14.isIdentifier(node) && node.text === hook.value) {
8396
8891
  const parent = node.parent;
8397
- if (ts13.isBindingElement(parent) || ts13.isPropertyAccessExpression(parent) || ts13.isShorthandPropertyAssignment(parent)) {
8892
+ if (ts14.isBindingElement(parent) || ts14.isPropertyAccessExpression(parent) || ts14.isShorthandPropertyAssignment(parent)) {
8398
8893
  return void 0;
8399
8894
  }
8400
8895
  return "value";
@@ -8404,16 +8899,16 @@ function isHookUsage(node, hook) {
8404
8899
  function topLevelJsxChildren(initial) {
8405
8900
  if (!initial) return void 0;
8406
8901
  let expression = initial;
8407
- while (ts13.isParenthesizedExpression(expression)) expression = expression.expression;
8408
- if (ts13.isJsxFragment(expression)) {
8902
+ while (ts14.isParenthesizedExpression(expression)) expression = expression.expression;
8903
+ if (ts14.isJsxFragment(expression)) {
8409
8904
  const children = expression.children.filter(
8410
- (c) => !ts13.isJsxText(c) && !ts13.isJsxSpreadAttribute(c)
8905
+ (c) => !ts14.isJsxText(c) && !ts14.isJsxSpreadAttribute(c)
8411
8906
  );
8412
8907
  return { root: expression, children };
8413
8908
  }
8414
- if (ts13.isJsxElement(expression)) {
8909
+ if (ts14.isJsxElement(expression)) {
8415
8910
  const children = expression.children.filter(
8416
- (c) => !ts13.isJsxText(c) && !ts13.isJsxSpreadAttribute(c)
8911
+ (c) => !ts14.isJsxText(c) && !ts14.isJsxSpreadAttribute(c)
8417
8912
  );
8418
8913
  return { root: expression, children };
8419
8914
  }
@@ -8427,8 +8922,8 @@ function collectUsesIn(child, hook) {
8427
8922
  positions.push(node);
8428
8923
  count += 1;
8429
8924
  }
8430
- if (ts13.isFunctionDeclaration(node) || ts13.isClassDeclaration(node)) return;
8431
- ts13.forEachChild(node, visit);
8925
+ if (ts14.isFunctionDeclaration(node) || ts14.isClassDeclaration(node)) return;
8926
+ ts14.forEachChild(node, visit);
8432
8927
  };
8433
8928
  visit(child);
8434
8929
  return { positions, count };
@@ -8442,7 +8937,7 @@ var soleStateOwnerRule = {
8442
8937
  }
8443
8938
  },
8444
8939
  create(context) {
8445
- const filename = path55.resolve(context.filename);
8940
+ const filename = path58.resolve(context.filename);
8446
8941
  if (!filename.endsWith(".tsx") && !filename.endsWith(".jsx")) return {};
8447
8942
  const text = context.sourceCode.text;
8448
8943
  const components = parseComponentInfo(text, filename);
@@ -8467,18 +8962,18 @@ var soleStateOwnerRule = {
8467
8962
  }
8468
8963
  };
8469
8964
  function analyzeSoleOwner(declaration, hook) {
8470
- const body = ts13.isFunctionDeclaration(declaration) ? declaration.body : void 0;
8471
- if (!body || !ts13.isBlock(body)) return void 0;
8965
+ const body = ts14.isFunctionDeclaration(declaration) ? declaration.body : void 0;
8966
+ if (!body || !ts14.isBlock(body)) return void 0;
8472
8967
  const returns = [];
8473
8968
  const visit = (node) => {
8474
- if (node !== body && (ts13.isFunctionLike(node) || ts13.isClassLike(node))) return;
8475
- if (ts13.isReturnStatement(node)) returns.push(node);
8476
- ts13.forEachChild(node, visit);
8969
+ if (node !== body && (ts14.isFunctionLike(node) || ts14.isClassLike(node))) return;
8970
+ if (ts14.isReturnStatement(node)) returns.push(node);
8971
+ ts14.forEachChild(node, visit);
8477
8972
  };
8478
8973
  visit(body);
8479
8974
  if (returns.length !== 1) return void 0;
8480
8975
  const single = returns[0];
8481
- if (!single?.expression || !ts13.isExpression(single.expression)) return void 0;
8976
+ if (!single?.expression || !ts14.isExpression(single.expression)) return void 0;
8482
8977
  const returnExpression = single.expression;
8483
8978
  const root = topLevelJsxChildren(returnExpression);
8484
8979
  if (!root || root.children.length === 0) return void 0;
@@ -8501,11 +8996,11 @@ function usesOutsideJsx(declaration, hook, children) {
8501
8996
  let outside = false;
8502
8997
  const visit = (node) => {
8503
8998
  if (outside) return;
8504
- if (node !== declaration && (ts13.isFunctionDeclaration(node) || ts13.isClassDeclaration(node))) return;
8999
+ if (node !== declaration && (ts14.isFunctionDeclaration(node) || ts14.isClassDeclaration(node))) return;
8505
9000
  if (isHookUsage(node, hook)) {
8506
9001
  let current = node;
8507
9002
  let isInJsxChild = false;
8508
- while (!ts13.isSourceFile(current)) {
9003
+ while (!ts14.isSourceFile(current)) {
8509
9004
  if (children.includes(current)) {
8510
9005
  isInJsxChild = true;
8511
9006
  break;
@@ -8514,14 +9009,14 @@ function usesOutsideJsx(declaration, hook, children) {
8514
9009
  }
8515
9010
  if (!isInJsxChild) outside = true;
8516
9011
  }
8517
- ts13.forEachChild(node, visit);
9012
+ ts14.forEachChild(node, visit);
8518
9013
  };
8519
9014
  visit(declaration);
8520
9015
  return outside;
8521
9016
  }
8522
9017
 
8523
9018
  // eslint/rules/source-under-src.ts
8524
- import path56 from "path";
9019
+ import path59 from "path";
8525
9020
  var NON_SOURCE_ROOT_DIRS = /* @__PURE__ */ new Set([
8526
9021
  ".agents",
8527
9022
  ".cache",
@@ -8562,14 +9057,14 @@ var sourceUnderSrcRule = {
8562
9057
  }
8563
9058
  },
8564
9059
  create(context) {
8565
- const filename = path56.resolve(context.filename);
9060
+ const filename = path59.resolve(context.filename);
8566
9061
  if (!MODULE_EXTENSION.test(filename)) return {};
8567
- const relative = path56.relative(context.cwd, filename).replace(/\\/g, "/");
9062
+ const relative = path59.relative(context.cwd, filename).replace(/\\/g, "/");
8568
9063
  if (relative === "src" || relative.startsWith("src/")) return {};
8569
9064
  const topLevel = relative.split("/")[0] ?? "";
8570
9065
  if (NON_SOURCE_ROOT_DIRS.has(topLevel)) return {};
8571
9066
  if (!relative.includes("/")) {
8572
- const basename = path56.basename(filename);
9067
+ const basename = path59.basename(filename);
8573
9068
  if (CONFIG_FILE.test(basename) || DECLARATION_FILE.test(basename) || basename.startsWith(".")) return {};
8574
9069
  }
8575
9070
  return {
@@ -8585,7 +9080,7 @@ var sourceUnderSrcRule = {
8585
9080
  };
8586
9081
 
8587
9082
  // eslint/rules/stay-flat.ts
8588
- import path57 from "path";
9083
+ import path60 from "path";
8589
9084
  var stayFlatRule = {
8590
9085
  meta: {
8591
9086
  schema: [],
@@ -8596,7 +9091,7 @@ var stayFlatRule = {
8596
9091
  },
8597
9092
  create(context) {
8598
9093
  const sourceRoot = sourceRootOf(context);
8599
- const file = path57.resolve(context.filename);
9094
+ const file = path60.resolve(context.filename);
8600
9095
  const segments = segmentsOf(file, sourceRoot);
8601
9096
  if (segments.length !== 3 || segments[0] !== "features") return {};
8602
9097
  const index = getProjectIndex(sourceRoot);
@@ -8636,7 +9131,7 @@ var stayFlatRule = {
8636
9131
  };
8637
9132
 
8638
9133
  // eslint/rules/support-file-placement.ts
8639
- import path58 from "path";
9134
+ import path61 from "path";
8640
9135
  var CONFIG_OWNED_FOLDERS = /* @__PURE__ */ new Set(["types", "constants"]);
8641
9136
  var EXPORT_KIND_BY_SUPPORT_FOLDER = /* @__PURE__ */ new Map([
8642
9137
  ["constants", "constant"],
@@ -8661,7 +9156,7 @@ var supportFilePlacementRule = {
8661
9156
  },
8662
9157
  create(context) {
8663
9158
  const sourceRoot = sourceRootOf(context);
8664
- const supportFile = path58.resolve(context.filename);
9159
+ const supportFile = path61.resolve(context.filename);
8665
9160
  const currentFolder = folderSegmentsOf(supportFile, sourceRoot);
8666
9161
  const supportFolder = currentFolder[currentFolder.length - 1];
8667
9162
  if (supportFolder === void 0 || !SUPPORT_FOLDERS.has(supportFolder)) return {};
@@ -8715,7 +9210,7 @@ var supportFilePlacementRule = {
8715
9210
 
8716
9211
  // eslint/rules/support-folder-shape.ts
8717
9212
  import fs6 from "fs";
8718
- import path59 from "path";
9213
+ import path62 from "path";
8719
9214
  var SUPPORT_FOLDERS4 = /* @__PURE__ */ new Set(["constants", "types", "schemas"]);
8720
9215
  var INDEX_NAMES2 = /* @__PURE__ */ new Set(["index.ts", "index.tsx", "index.mts", "index.cts"]);
8721
9216
  var supportFolderShapeRule = {
@@ -8727,12 +9222,12 @@ var supportFolderShapeRule = {
8727
9222
  }
8728
9223
  },
8729
9224
  create(context) {
8730
- const filename = path59.resolve(context.filename);
8731
- const baseName = path59.basename(filename);
9225
+ const filename = path62.resolve(context.filename);
9226
+ const baseName = path62.basename(filename);
8732
9227
  if (!INDEX_NAMES2.has(baseName)) return {};
8733
- const folder = path59.basename(path59.dirname(filename));
9228
+ const folder = path62.basename(path62.dirname(filename));
8734
9229
  if (!SUPPORT_FOLDERS4.has(folder)) return {};
8735
- const directory = path59.dirname(filename);
9230
+ const directory = path62.dirname(filename);
8736
9231
  let entries;
8737
9232
  try {
8738
9233
  entries = fs6.readdirSync(directory);
@@ -8750,7 +9245,7 @@ var supportFolderShapeRule = {
8750
9245
  for (const match of source.matchAll(exportPattern)) {
8751
9246
  hasAnyReExport = true;
8752
9247
  const specifier = match.groups?.specifier;
8753
- if (specifier?.startsWith(".")) exportedFiles.add(path59.basename(specifier));
9248
+ if (specifier?.startsWith(".")) exportedFiles.add(path62.basename(specifier));
8754
9249
  }
8755
9250
  const guide = `docs/next-codebase-guide/rules/${folder === "constants" ? "constants" : "types-and-schemas"}-rule.md`;
8756
9251
  if (siblingModules.length === 0) {
@@ -8929,24 +9424,24 @@ var baseLayerPairRule = {
8929
9424
 
8930
9425
  // eslint/rules/tailwind/css-entry-point.ts
8931
9426
  import { statSync as statSync4 } from "fs";
8932
- import path62 from "path";
9427
+ import path65 from "path";
8933
9428
 
8934
9429
  // eslint/rules/tailwind/source-files.ts
8935
- import { readdirSync as readdirSync3, readFileSync as readFileSync11, statSync as statSync3 } from "fs";
8936
- import path60 from "path";
9430
+ import { readdirSync as readdirSync5, readFileSync as readFileSync13, statSync as statSync3 } from "fs";
9431
+ import path63 from "path";
8937
9432
  var CSS_EXTENSIONS = [".css"];
8938
9433
  var MODULE_EXTENSIONS4 = [".ts", ".tsx", ".mts", ".cts", ".js", ".jsx", ".mjs", ".cjs"];
8939
9434
  var SOURCE_EXTENSIONS = [...MODULE_EXTENSIONS4, ...CSS_EXTENSIONS];
8940
9435
  function findFiles(dir, extensions) {
8941
9436
  let entries;
8942
9437
  try {
8943
- entries = readdirSync3(dir);
9438
+ entries = readdirSync5(dir);
8944
9439
  } catch {
8945
9440
  return [];
8946
9441
  }
8947
9442
  return entries.flatMap((entry) => {
8948
9443
  if (entry.startsWith(".") || entry === "node_modules") return [];
8949
- const entryPath = path60.join(dir, entry);
9444
+ const entryPath = path63.join(dir, entry);
8950
9445
  let stats;
8951
9446
  try {
8952
9447
  stats = statSync3(entryPath);
@@ -8954,7 +9449,7 @@ function findFiles(dir, extensions) {
8954
9449
  return [];
8955
9450
  }
8956
9451
  if (stats.isDirectory()) return findFiles(entryPath, extensions);
8957
- return extensions.includes(path60.extname(entry)) ? [entryPath] : [];
9452
+ return extensions.includes(path63.extname(entry)) ? [entryPath] : [];
8958
9453
  });
8959
9454
  }
8960
9455
  function cachedTextReader() {
@@ -8963,7 +9458,7 @@ function cachedTextReader() {
8963
9458
  let text = texts.get(file);
8964
9459
  if (text === void 0) {
8965
9460
  try {
8966
- text = readFileSync11(file, "utf8");
9461
+ text = readFileSync13(file, "utf8");
8967
9462
  } catch {
8968
9463
  text = "";
8969
9464
  }
@@ -8977,7 +9472,7 @@ function escapeRegExp(text) {
8977
9472
  }
8978
9473
 
8979
9474
  // eslint/rules/tailwind/stylesheet-graph.ts
8980
- import path61 from "path";
9475
+ import path64 from "path";
8981
9476
  function registersTailwind(text) {
8982
9477
  return /@import\s+(?:url\(\s*)?["']tailwindcss["']\s*\)?/i.test(text);
8983
9478
  }
@@ -8991,25 +9486,25 @@ function moduleImports(text, fileName) {
8991
9486
  return new RegExp(`(?:import|require)\\s*\\(?\\s*["'][^"']*${escaped}["']`, "i").test(text);
8992
9487
  }
8993
9488
  function resolveSpecifier2(fromFile, spec, sourceRoot) {
8994
- if (spec.startsWith("/")) return path61.resolve(spec);
8995
- if (spec.startsWith("./") || spec.startsWith("../")) return path61.resolve(path61.dirname(fromFile), spec);
8996
- if (spec.startsWith("@/")) return path61.resolve(sourceRoot, spec.slice(2));
9489
+ if (spec.startsWith("/")) return path64.resolve(spec);
9490
+ if (spec.startsWith("./") || spec.startsWith("../")) return path64.resolve(path64.dirname(fromFile), spec);
9491
+ if (spec.startsWith("@/")) return path64.resolve(sourceRoot, spec.slice(2));
8997
9492
  return void 0;
8998
9493
  }
8999
9494
  function buildStylesheetGraph(options) {
9000
9495
  const { cssFiles, sourceRoot, textOf } = options;
9001
- const cssSet = new Set(cssFiles.map((file) => path61.normalize(file)));
9496
+ const cssSet = new Set(cssFiles.map((file) => path64.normalize(file)));
9002
9497
  const globals = cssFiles.filter((file) => registersTailwind(textOf(file)));
9003
9498
  const reachable = /* @__PURE__ */ new Set();
9004
9499
  const queue = [...globals];
9005
- for (const global of globals) reachable.add(path61.normalize(global));
9500
+ for (const global of globals) reachable.add(path64.normalize(global));
9006
9501
  while (queue.length > 0) {
9007
9502
  const from = queue.shift();
9008
9503
  if (!from) continue;
9009
9504
  for (const spec of importedSpecifiers(textOf(from))) {
9010
9505
  const target = resolveSpecifier2(from, spec, sourceRoot);
9011
9506
  if (!target) continue;
9012
- const normalized = path61.normalize(target);
9507
+ const normalized = path64.normalize(target);
9013
9508
  if (cssSet.has(normalized) && !reachable.has(normalized)) {
9014
9509
  reachable.add(normalized);
9015
9510
  queue.push(normalized);
@@ -9021,7 +9516,7 @@ function buildStylesheetGraph(options) {
9021
9516
  for (const spec of importedSpecifiers(textOf(global))) {
9022
9517
  const target = resolveSpecifier2(global, spec, sourceRoot);
9023
9518
  if (!target) continue;
9024
- const normalized = path61.normalize(target);
9519
+ const normalized = path64.normalize(target);
9025
9520
  if (cssSet.has(normalized)) directChildren.add(normalized);
9026
9521
  }
9027
9522
  }
@@ -9029,8 +9524,8 @@ function buildStylesheetGraph(options) {
9029
9524
  }
9030
9525
 
9031
9526
  // eslint/rules/tailwind/css-entry-point.ts
9032
- var APP_STYLES_DIR = path62.join("app", "styles");
9033
- var GLOBAL_STYLESHEET_PATH = path62.join(APP_STYLES_DIR, "globals.css");
9527
+ var APP_STYLES_DIR = path65.join("app", "styles");
9528
+ var GLOBAL_STYLESHEET_PATH = path65.join(APP_STYLES_DIR, "globals.css");
9034
9529
  var cssEntryPointRule = {
9035
9530
  meta: {
9036
9531
  schema: [],
@@ -9056,8 +9551,8 @@ var cssEntryPointRule = {
9056
9551
  return {
9057
9552
  "StyleSheet:exit"(node) {
9058
9553
  if (globals.length === 0) return;
9059
- const current = path62.normalize(path62.resolve(context.filename));
9060
- const relative = path62.relative(sourceRoot, current);
9554
+ const current = path65.normalize(path65.resolve(context.filename));
9555
+ const relative = path65.relative(sourceRoot, current);
9061
9556
  if (globals.includes(current)) {
9062
9557
  if (globals.length > 1) {
9063
9558
  context.report({
@@ -9073,7 +9568,7 @@ var cssEntryPointRule = {
9073
9568
  });
9074
9569
  return;
9075
9570
  }
9076
- const basename = path62.basename(current);
9571
+ const basename = path65.basename(current);
9077
9572
  const importCount = moduleFiles.filter((modulePath) => moduleImports(textOf(modulePath), basename)).length;
9078
9573
  if (importCount !== 1) {
9079
9574
  context.report({
@@ -9083,7 +9578,7 @@ var cssEntryPointRule = {
9083
9578
  }
9084
9579
  return;
9085
9580
  }
9086
- const isInAppStyles = relative === APP_STYLES_DIR || relative.startsWith(`${APP_STYLES_DIR}${path62.sep}`);
9581
+ const isInAppStyles = relative === APP_STYLES_DIR || relative.startsWith(`${APP_STYLES_DIR}${path65.sep}`);
9087
9582
  if (!isInAppStyles) {
9088
9583
  context.report({
9089
9584
  node,
@@ -9572,7 +10067,7 @@ var tailwindRules = {
9572
10067
  };
9573
10068
 
9574
10069
  // eslint/rules/type-extraction.ts
9575
- import path63 from "path";
10070
+ import path66 from "path";
9576
10071
  var typeExtractionRule = {
9577
10072
  meta: {
9578
10073
  schema: [],
@@ -9583,7 +10078,7 @@ var typeExtractionRule = {
9583
10078
  },
9584
10079
  create(context) {
9585
10080
  const sourceRoot = sourceRootOf(context);
9586
- const file = path63.resolve(context.filename);
10081
+ const file = path66.resolve(context.filename);
9587
10082
  const segments = segmentsOf(file, sourceRoot);
9588
10083
  if (segments.length === 0) return {};
9589
10084
  const index = getProjectIndex(sourceRoot);
@@ -9722,9 +10217,9 @@ var uiStateRule = {
9722
10217
  };
9723
10218
 
9724
10219
  // eslint/rules/unknown-utility.ts
9725
- import { existsSync as existsSync6, readdirSync as readdirSync4, readFileSync as readFileSync12, statSync as statSync6 } from "fs";
10220
+ import { existsSync as existsSync8, readdirSync as readdirSync6, readFileSync as readFileSync14, statSync as statSync6 } from "fs";
9726
10221
  import { createRequire } from "module";
9727
- import path64 from "path";
10222
+ import path67 from "path";
9728
10223
  var PREFIX_NAMESPACES = {
9729
10224
  bg: ["color"],
9730
10225
  text: ["color", "text"],
@@ -9958,13 +10453,13 @@ function isBuiltInTailwindUtility(utility) {
9958
10453
  function stylesheetFiles(dir) {
9959
10454
  let entries;
9960
10455
  try {
9961
- entries = readdirSync4(dir);
10456
+ entries = readdirSync6(dir);
9962
10457
  } catch {
9963
10458
  return [];
9964
10459
  }
9965
10460
  return entries.flatMap((entry) => {
9966
10461
  if (entry.startsWith(".") || entry === "node_modules") return [];
9967
- const entryPath = path64.join(dir, entry);
10462
+ const entryPath = path67.join(dir, entry);
9968
10463
  let stats;
9969
10464
  try {
9970
10465
  stats = statSync6(entryPath);
@@ -9972,7 +10467,7 @@ function stylesheetFiles(dir) {
9972
10467
  return [];
9973
10468
  }
9974
10469
  if (stats.isDirectory()) return stylesheetFiles(entryPath);
9975
- return path64.extname(entry) === ".css" ? [entryPath] : [];
10470
+ return path67.extname(entry) === ".css" ? [entryPath] : [];
9976
10471
  });
9977
10472
  }
9978
10473
  function packageNameOf(specifier) {
@@ -9983,24 +10478,24 @@ function packageNameOf(specifier) {
9983
10478
  function resolvePackageStylesheet(fromFile, specifier) {
9984
10479
  const packageName = packageNameOf(specifier);
9985
10480
  if (!packageName || packageName === "tailwindcss") return void 0;
9986
- let directory = path64.dirname(fromFile);
9987
- while (directory !== path64.dirname(directory)) {
9988
- const packageRoot = path64.join(directory, "node_modules", packageName);
9989
- const manifestPath = path64.join(packageRoot, "package.json");
9990
- if (existsSync6(manifestPath)) {
10481
+ let directory = path67.dirname(fromFile);
10482
+ while (directory !== path67.dirname(directory)) {
10483
+ const packageRoot = path67.join(directory, "node_modules", packageName);
10484
+ const manifestPath = path67.join(packageRoot, "package.json");
10485
+ if (existsSync8(manifestPath)) {
9991
10486
  try {
9992
- const manifest = readFileSync12(manifestPath, "utf8");
10487
+ const manifest = readFileSync14(manifestPath, "utf8");
9993
10488
  const stylesheet = /"style"\s*:\s*"(?<file>[^"]+\.css)"/.exec(manifest)?.groups?.file;
9994
10489
  const main = /"main"\s*:\s*"(?<file>[^"]+\.css)"/.exec(manifest)?.groups?.file;
9995
10490
  const target = stylesheet ?? main;
9996
10491
  if (!target) return void 0;
9997
- const resolved = path64.resolve(packageRoot, target);
9998
- return existsSync6(resolved) ? resolved : void 0;
10492
+ const resolved = path67.resolve(packageRoot, target);
10493
+ return existsSync8(resolved) ? resolved : void 0;
9999
10494
  } catch {
10000
10495
  return void 0;
10001
10496
  }
10002
10497
  }
10003
- directory = path64.dirname(directory);
10498
+ directory = path67.dirname(directory);
10004
10499
  }
10005
10500
  return void 0;
10006
10501
  }
@@ -10009,7 +10504,7 @@ function inventoryStylesheetFiles(projectFiles) {
10009
10504
  for (const file of projectFiles) {
10010
10505
  let css2;
10011
10506
  try {
10012
- css2 = readFileSync12(file, "utf8");
10507
+ css2 = readFileSync14(file, "utf8");
10013
10508
  } catch {
10014
10509
  continue;
10015
10510
  }
@@ -10075,7 +10570,7 @@ function readInventory(files) {
10075
10570
  for (const file of files) {
10076
10571
  let css2;
10077
10572
  try {
10078
- css2 = readFileSync12(file, "utf8");
10573
+ css2 = readFileSync14(file, "utf8");
10079
10574
  } catch {
10080
10575
  continue;
10081
10576
  }
@@ -10251,7 +10746,7 @@ var unknownUtilityRule = {
10251
10746
  };
10252
10747
 
10253
10748
  // eslint/rules/util-file-name.ts
10254
- import path65 from "path";
10749
+ import path68 from "path";
10255
10750
  function toKebabCase2(value) {
10256
10751
  return value.replace(/(?<lower>[a-z0-9])(?<upper>[A-Z])/g, "$<lower>-$<upper>").replace(/(?<first>[A-Z])(?<rest>[A-Z][a-z])/g, "$<first>-$<rest>").toLowerCase();
10257
10752
  }
@@ -10264,7 +10759,7 @@ var utilFileNameRule = {
10264
10759
  }
10265
10760
  },
10266
10761
  create(context) {
10267
- const filename = path65.resolve(context.filename);
10762
+ const filename = path68.resolve(context.filename);
10268
10763
  const segments = filename.replace(/\\/g, "/").split("/");
10269
10764
  if (!segments.includes("utils")) return {};
10270
10765
  let module;
@@ -10278,13 +10773,13 @@ var utilFileNameRule = {
10278
10773
  const functionName = functions[0]?.name;
10279
10774
  if (!functionName) return {};
10280
10775
  const expected = toKebabCase2(functionName);
10281
- const actual = path65.basename(filename, path65.extname(filename));
10776
+ const actual = path68.basename(filename, path68.extname(filename));
10282
10777
  if (!expected || actual === expected) return {};
10283
10778
  return {
10284
10779
  Program(node) {
10285
10780
  context.report({
10286
10781
  node,
10287
- message: `A utility file exporting ${functionName} must be named ${expected}.${path65.extname(filename).slice(1)}.`
10782
+ message: `A utility file exporting ${functionName} must be named ${expected}.${path68.extname(filename).slice(1)}.`
10288
10783
  });
10289
10784
  }
10290
10785
  };
@@ -10292,7 +10787,7 @@ var utilFileNameRule = {
10292
10787
  };
10293
10788
 
10294
10789
  // eslint/rules/value-extraction.ts
10295
- import path66 from "path";
10790
+ import path69 from "path";
10296
10791
  var valueExtractionRule = {
10297
10792
  meta: {
10298
10793
  schema: [],
@@ -10303,7 +10798,7 @@ var valueExtractionRule = {
10303
10798
  },
10304
10799
  create(context) {
10305
10800
  const sourceRoot = sourceRootOf(context);
10306
- const file = path66.resolve(context.filename);
10801
+ const file = path69.resolve(context.filename);
10307
10802
  const segments = segmentsOf(file, sourceRoot);
10308
10803
  if (segments.length === 0 || segments[0] !== "app") return {};
10309
10804
  const index = getProjectIndex(sourceRoot);
@@ -10324,8 +10819,8 @@ var valueExtractionRule = {
10324
10819
  };
10325
10820
 
10326
10821
  // eslint/rules/vulyk/tracked-docs.ts
10327
- import { existsSync as existsSync7, readFileSync as readFileSync13 } from "fs";
10328
- import path67 from "path";
10822
+ import { existsSync as existsSync9, readFileSync as readFileSync15 } from "fs";
10823
+ import path70 from "path";
10329
10824
  var PASIKA_REPO = "Bredansky/pasika";
10330
10825
  var BASE_REQUIRED_TRACKED_DOCS = [
10331
10826
  { name: "documentation-guide", path: "docs/documentation-guide" },
@@ -10336,13 +10831,13 @@ var NEXTJS_REQUIRED_TRACKED_DOCS = [
10336
10831
  { name: "next-codebase-guide", path: "docs/next-codebase-guide" },
10337
10832
  { name: "next-tailwind-guide", path: "docs/next-tailwind-guide" }
10338
10833
  ];
10339
- function memberName7(member) {
10834
+ function memberName8(member) {
10340
10835
  return member.name.type === "String" ? member.name.value : member.name.name;
10341
10836
  }
10342
10837
  function hasDependency(root, name) {
10343
- const section = root.members.find((member) => memberName7(member) === "dependencies");
10838
+ const section = root.members.find((member) => memberName8(member) === "dependencies");
10344
10839
  if (section?.value.type !== "Object") return false;
10345
- return section.value.members.some((member) => memberName7(member) === name);
10840
+ return section.value.members.some((member) => memberName8(member) === name);
10346
10841
  }
10347
10842
  var trackedDocsRule = {
10348
10843
  meta: {
@@ -10358,16 +10853,16 @@ var trackedDocsRule = {
10358
10853
  if (!context.filename.endsWith("package.json")) return;
10359
10854
  const root = node.body;
10360
10855
  if (root.type !== "Object") return;
10361
- const projectRoot = path67.dirname(path67.resolve(context.filename));
10362
- const configPath = path67.join(projectRoot, "vulyk.config.ts");
10363
- if (!existsSync7(configPath)) {
10856
+ const projectRoot = path70.dirname(path70.resolve(context.filename));
10857
+ const configPath = path70.join(projectRoot, "vulyk.config.ts");
10858
+ if (!existsSync9(configPath)) {
10364
10859
  context.report({
10365
10860
  node,
10366
10861
  message: "No vulyk.config.ts found. Run npx vulyk init to create one that tracks the framework's required tracked docs."
10367
10862
  });
10368
10863
  return;
10369
10864
  }
10370
- const config = readFileSync13(configPath, "utf8");
10865
+ const config = readFileSync15(configPath, "utf8");
10371
10866
  if (!config.includes(PASIKA_REPO)) {
10372
10867
  context.report({
10373
10868
  node,
@@ -10384,8 +10879,8 @@ var trackedDocsRule = {
10384
10879
  });
10385
10880
  }
10386
10881
  }
10387
- const agentsPath = path67.join(projectRoot, "AGENTS.md");
10388
- if (!existsSync7(agentsPath)) {
10882
+ const agentsPath = path70.join(projectRoot, "AGENTS.md");
10883
+ if (!existsSync9(agentsPath)) {
10389
10884
  context.report({
10390
10885
  node,
10391
10886
  message: "No AGENTS.md found. Run npx vulyk agents to generate the agent file that routes to the tracked docs."
@@ -10397,14 +10892,14 @@ var trackedDocsRule = {
10397
10892
  };
10398
10893
 
10399
10894
  // eslint/rules/vulyk/vulyk-dependency.ts
10400
- function memberName8(member) {
10895
+ function memberName9(member) {
10401
10896
  return member.name.type === "String" ? member.name.value : member.name.name;
10402
10897
  }
10403
10898
  function dependency(root, sectionName) {
10404
10899
  if (root.type !== "Object") return void 0;
10405
- const section = root.members.find((member) => memberName8(member) === sectionName);
10900
+ const section = root.members.find((member) => memberName9(member) === sectionName);
10406
10901
  if (section?.value.type !== "Object") return void 0;
10407
- return section.value.members.find((member) => memberName8(member) === "vulyk");
10902
+ return section.value.members.find((member) => memberName9(member) === "vulyk");
10408
10903
  }
10409
10904
  var vulykDependencyRule = {
10410
10905
  meta: {
@@ -10445,9 +10940,9 @@ var vulykRules = {
10445
10940
  // eslint/rules/with-response-helper.ts
10446
10941
  var HELPER3 = "withResponse";
10447
10942
  var ENTRY3 = "pasika/with-response";
10448
- var DOC8 = "docs/pasika-adoption-guide/rules/with-response-helper-rule.md";
10449
- var DECLARED3 = `A repository must not declare its own ${HELPER3}; import it from ${ENTRY3}. See ${DOC8}`;
10450
- var IMPORTED3 = `${HELPER3} must be imported from ${ENTRY3}. See ${DOC8}`;
10943
+ var DOC9 = "docs/pasika-adoption-guide/rules/with-response-helper-rule.md";
10944
+ var DECLARED3 = `A repository must not declare its own ${HELPER3}; import it from ${ENTRY3}. See ${DOC9}`;
10945
+ var IMPORTED3 = `${HELPER3} must be imported from ${ENTRY3}. See ${DOC9}`;
10451
10946
  function isNamed3(node, name) {
10452
10947
  return node?.type === "Identifier" && node.name === name;
10453
10948
  }
@@ -10484,7 +10979,7 @@ var withResponseHelperRule = {
10484
10979
 
10485
10980
  // eslint/rules/zirka-baseline.ts
10486
10981
  import fs7 from "fs";
10487
- import path68 from "path";
10982
+ import path71 from "path";
10488
10983
  var ESLINT_CONFIG = /^eslint\.config\.(?:ts|mts|cts|js|mjs|cjs)$/;
10489
10984
  var PRETTIER_CONFIGS = [
10490
10985
  "prettier.config.mjs",
@@ -10503,10 +10998,10 @@ var zirkaBaselineRule = {
10503
10998
  }
10504
10999
  },
10505
11000
  create(context) {
10506
- const filename = path68.resolve(context.filename);
10507
- const basename = path68.basename(filename);
11001
+ const filename = path71.resolve(context.filename);
11002
+ const basename = path71.basename(filename);
10508
11003
  if (!ESLINT_CONFIG.test(basename)) return {};
10509
- const projectRoot = path68.dirname(filename);
11004
+ const projectRoot = path71.dirname(filename);
10510
11005
  const report3 = (message) => {
10511
11006
  context.report({
10512
11007
  node: context.sourceCode.ast,
@@ -10521,7 +11016,7 @@ var zirkaBaselineRule = {
10521
11016
  'ESLint config must take its configuration from zirka (import { styleguide } from "zirka") instead of restating rules locally.'
10522
11017
  );
10523
11018
  }
10524
- const tsconfigPath = path68.join(projectRoot, "tsconfig.json");
11019
+ const tsconfigPath = path71.join(projectRoot, "tsconfig.json");
10525
11020
  if (!fs7.existsSync(tsconfigPath)) {
10526
11021
  report3('No tsconfig.json found. Create one extending the zirka TypeScript base config ("zirka/typescript").');
10527
11022
  } else {
@@ -10539,13 +11034,13 @@ var zirkaBaselineRule = {
10539
11034
  report3('tsconfig.json must extend the zirka TypeScript base config ("zirka/typescript").');
10540
11035
  }
10541
11036
  }
10542
- const prettierConfigFile = PRETTIER_CONFIGS.find((name) => fs7.existsSync(path68.join(projectRoot, name)));
11037
+ const prettierConfigFile = PRETTIER_CONFIGS.find((name) => fs7.existsSync(path71.join(projectRoot, name)));
10543
11038
  if (!prettierConfigFile) {
10544
11039
  report3(
10545
11040
  "No prettier config found. Create one that takes its configuration from zirka (styleguide({ prettier: true }).prettierConfig)."
10546
11041
  );
10547
11042
  } else {
10548
- const content = fs7.readFileSync(path68.join(projectRoot, prettierConfigFile), "utf8");
11043
+ const content = fs7.readFileSync(path71.join(projectRoot, prettierConfigFile), "utf8");
10549
11044
  if (!content.includes("zirka")) {
10550
11045
  report3(
10551
11046
  "The prettier config must take its configuration from zirka (styleguide({ prettier: true }).prettierConfig) instead of restating it locally."
@@ -10568,10 +11063,10 @@ function referencesZirka(sourceCode) {
10568
11063
  // eslint/rules/zod-fetch-helper.ts
10569
11064
  var HELPER4 = "zodFetch";
10570
11065
  var ENTRY4 = "pasika/zod-fetch";
10571
- var DOC9 = "docs/pasika-adoption-guide/rules/zod-fetch-helper-rule.md";
10572
- var FETCHED = `fetch must not be called; make the request through ${HELPER4} from ${ENTRY4}. See ${DOC9}`;
10573
- var DECLARED4 = `A file must not declare its own ${HELPER4}; import it from ${ENTRY4}. See ${DOC9}`;
10574
- var IMPORTED4 = `${HELPER4} must be imported from ${ENTRY4}. See ${DOC9}`;
11066
+ var DOC10 = "docs/pasika-adoption-guide/rules/zod-fetch-helper-rule.md";
11067
+ var FETCHED = `fetch must not be called; make the request through ${HELPER4} from ${ENTRY4}. See ${DOC10}`;
11068
+ var DECLARED4 = `A file must not declare its own ${HELPER4}; import it from ${ENTRY4}. See ${DOC10}`;
11069
+ var IMPORTED4 = `${HELPER4} must be imported from ${ENTRY4}. See ${DOC10}`;
10575
11070
  var GLOBAL_OBJECTS = /* @__PURE__ */ new Set(["globalThis", "window", "self", "global"]);
10576
11071
  var TEST_FILE2 = /(?:^|[\\/])(?:__tests__|tests)[\\/]|[.](?:test|spec)[.][cm]?[jt]sx?$/;
10577
11072
  function isNamed4(node, name) {
@@ -10691,14 +11186,14 @@ var zodSchemaValidationRule = {
10691
11186
  };
10692
11187
 
10693
11188
  // eslint/ts-alignment.ts
10694
- import { readFileSync as readFileSync14 } from "fs";
11189
+ import { readFileSync as readFileSync16 } from "fs";
10695
11190
  import { createRequire as createRequire2 } from "module";
10696
11191
  import { join } from "path";
10697
11192
  var ownRequire = createRequire2(import.meta.url);
10698
11193
  var majorOf = (version) => Number(version.split(".")[0]);
10699
11194
  function versionOf(packagePath) {
10700
11195
  try {
10701
- const parsed = JSON.parse(readFileSync14(packagePath, "utf8"));
11196
+ const parsed = JSON.parse(readFileSync16(packagePath, "utf8"));
10702
11197
  if (typeof parsed !== "object" || parsed === null || !("version" in parsed)) return null;
10703
11198
  return typeof parsed.version === "string" ? parsed.version : null;
10704
11199
  } catch {