pasika 0.10.101 → 0.10.103

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,145 @@ 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
+ const checkJobs = Object.values(jobs(check));
6647
+ const allSteps = checkJobs.flatMap(steps);
6648
+ for (const job of checkJobs) {
6649
+ const jobSteps = steps(job);
6650
+ const firstCheck = jobSteps.findIndex((step) => requiredScripts.some((name) => runsScript(step.run, name)));
6651
+ if (firstCheck < 0) continue;
6652
+ const checkout = jobSteps.findIndex((step) => usesAction(step.uses, "actions/checkout"));
6653
+ const install = jobSteps.findIndex((step) => runsNpmCi(step.run));
6654
+ if (checkout < 0 || checkout >= firstCheck) {
6655
+ report3("GitHub Actions checks must check out the repository before running npm scripts.");
6656
+ }
6657
+ if (install < 0 || install >= firstCheck || checkout >= 0 && install <= checkout) {
6658
+ report3("GitHub Actions checks must install dependencies with npm ci.");
6659
+ }
6660
+ }
6661
+ for (const name of requiredScripts) {
6662
+ if (!allSteps.some((step) => runsScript(step.run, name))) {
6663
+ report3(`GitHub Actions checks must run npm run ${name}.`);
6664
+ }
6665
+ }
6666
+ const coverage = scripts.get("test:unit:coverage:check");
6667
+ 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)) {
6668
+ report3(
6669
+ "package.json must declare test:unit:coverage:check that runs coverage with autoUpdate=false and verifies no Git diff."
6670
+ );
6671
+ }
6672
+ }
6673
+ };
6674
+ }
6675
+ };
6676
+
6677
+ // eslint/rules/package-json/exact-version.ts
6678
+ function memberName3(member) {
6679
+ return member.name.type === "String" ? member.name.value : member.name.name;
6680
+ }
6291
6681
  var EXACT_VERSION_PATTERN = /^\d+\.\d+\.\d+$/;
6292
6682
  function memberValue(member) {
6293
6683
  return member.value.type === "String" ? member.value.value : null;
@@ -6306,7 +6696,7 @@ var exactVersionRule = {
6306
6696
  const root = node.body;
6307
6697
  if (root.type !== "Object") return;
6308
6698
  for (const key of ["dependencies", "devDependencies"]) {
6309
- const section = root.members.find((member) => memberName2(member) === key);
6699
+ const section = root.members.find((member) => memberName3(member) === key);
6310
6700
  if (section?.value.type !== "Object") continue;
6311
6701
  for (const member of section.value.members) {
6312
6702
  const version = memberValue(member);
@@ -6314,7 +6704,7 @@ var exactVersionRule = {
6314
6704
  if (!EXACT_VERSION_PATTERN.test(version)) {
6315
6705
  context.report({
6316
6706
  node: member,
6317
- message: `${memberName2(member)} must pin an exact version (e.g. "1.2.3"), not a range or cap such as "${version}".`
6707
+ message: `${memberName3(member)} must pin an exact version (e.g. "1.2.3"), not a range or cap such as "${version}".`
6318
6708
  });
6319
6709
  }
6320
6710
  }
@@ -6325,7 +6715,7 @@ var exactVersionRule = {
6325
6715
  };
6326
6716
 
6327
6717
  // eslint/rules/package-json/lint-setup.ts
6328
- function memberName3(member) {
6718
+ function memberName4(member) {
6329
6719
  return member.name.type === "String" ? member.name.value : member.name.name;
6330
6720
  }
6331
6721
  function memberValue2(member) {
@@ -6367,9 +6757,9 @@ var lintSetupRule = {
6367
6757
  Document(node) {
6368
6758
  const root = node.body;
6369
6759
  if (root.type !== "Object") return;
6370
- const scripts = root.members.find((member) => memberName3(member) === "scripts");
6760
+ const scripts = root.members.find((member) => memberName4(member) === "scripts");
6371
6761
  const scriptMembers = scripts?.value.type === "Object" ? scripts.value.members : [];
6372
- const findScript = (name) => scriptMembers.find((member) => memberName3(member) === name);
6762
+ const findScript = (name) => scriptMembers.find((member) => memberName4(member) === name);
6373
6763
  const lint = findScript("lint");
6374
6764
  const lintCommand = memberValue2(lint);
6375
6765
  if (lintCommand === void 0 || !runsEslintDirectly(lintCommand) || !REPOSITORY_ARGUMENT_PATTERN.test(lintCommand)) {
@@ -6402,10 +6792,10 @@ var lintSetupRule = {
6402
6792
  message: 'package.json must declare a "format:staged" script that runs prettier with no repository-wide argument (e.g. "prettier --write").'
6403
6793
  });
6404
6794
  }
6405
- const lintStagedConfig = root.members.find((member) => memberName3(member) === "lint-staged");
6795
+ const lintStagedConfig = root.members.find((member) => memberName4(member) === "lint-staged");
6406
6796
  const stagedMembers = lintStagedConfig?.value.type === "Object" ? lintStagedConfig.value.members : [];
6407
6797
  const runsStagedScriptForGlob = (name, matchesGlob) => stagedMembers.some(
6408
- (member) => matchesGlob(memberName3(member)) && stringValues(member.value).some((command) => runsNamedScript(command, name))
6798
+ (member) => matchesGlob(memberName4(member)) && stringValues(member.value).some((command) => runsNamedScript(command, name))
6409
6799
  );
6410
6800
  const runsStagedScriptForExtension = (name, extension) => runsStagedScriptForGlob(name, (glob) => globIncludesExtension(glob, extension));
6411
6801
  const hasStagedSourceLint = runsStagedScriptForGlob("lint:staged", (glob) => SOURCE_GLOB_PATTERN.test(glob));
@@ -6456,13 +6846,13 @@ var NEXTJS_STACK_DEV_DEPENDENCIES = [
6456
6846
  "@testing-library/react",
6457
6847
  "@testing-library/dom"
6458
6848
  ];
6459
- function memberName4(member) {
6849
+ function memberName5(member) {
6460
6850
  return member.name.type === "String" ? member.name.value : member.name.name;
6461
6851
  }
6462
6852
  function sectionPackages(root, section) {
6463
- const member = root.type === "Object" ? root.members.find((entry) => memberName4(entry) === section) : void 0;
6853
+ const member = root.type === "Object" ? root.members.find((entry) => memberName5(entry) === section) : void 0;
6464
6854
  if (member?.value.type !== "Object") return /* @__PURE__ */ new Set();
6465
- return new Set(member.value.members.map(memberName4));
6855
+ return new Set(member.value.members.map(memberName5));
6466
6856
  }
6467
6857
  var nextjsStackRule = {
6468
6858
  meta: {
@@ -6499,9 +6889,9 @@ var nextjsStackRule = {
6499
6889
  };
6500
6890
 
6501
6891
  // 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) {
6892
+ import { existsSync as existsSync7, readFileSync as readFileSync12 } from "fs";
6893
+ import path47 from "path";
6894
+ function memberName6(member) {
6505
6895
  return member.name.type === "String" ? member.name.value : member.name.name;
6506
6896
  }
6507
6897
  function memberValue3(member) {
@@ -6539,9 +6929,9 @@ var vitestCoverageRule = {
6539
6929
  Document(node) {
6540
6930
  const root = node.body;
6541
6931
  if (root.type !== "Object") return;
6542
- const devDependencies = root.members.find((member) => memberName5(member) === "devDependencies");
6932
+ const devDependencies = root.members.find((member) => memberName6(member) === "devDependencies");
6543
6933
  const devDependencyNames = new Set(
6544
- devDependencies?.value.type === "Object" ? devDependencies.value.members.map(memberName5) : []
6934
+ devDependencies?.value.type === "Object" ? devDependencies.value.members.map(memberName6) : []
6545
6935
  );
6546
6936
  if (!devDependencyNames.has("vitest")) {
6547
6937
  context.report({ node, message: "vitest must be listed in package.json as a devDependency." });
@@ -6552,9 +6942,9 @@ var vitestCoverageRule = {
6552
6942
  message: "@vitest/coverage-v8 must be listed in package.json as a devDependency."
6553
6943
  });
6554
6944
  }
6555
- const scripts = root.members.find((member) => memberName5(member) === "scripts");
6945
+ const scripts = root.members.find((member) => memberName6(member) === "scripts");
6556
6946
  const scriptMembers = scripts?.value.type === "Object" ? scripts.value.members : [];
6557
- const unit = scriptMembers.find((member) => memberName5(member) === "test:unit");
6947
+ const unit = scriptMembers.find((member) => memberName6(member) === "test:unit");
6558
6948
  const unitCommand = memberValue3(unit);
6559
6949
  if (unitCommand === void 0 || !/\bvitest\b/.test(unitCommand) || COVERAGE_FLAG_PATTERN.test(unitCommand)) {
6560
6950
  context.report({
@@ -6562,7 +6952,7 @@ var vitestCoverageRule = {
6562
6952
  message: 'package.json must declare a "test:unit" script that runs Vitest without coverage.'
6563
6953
  });
6564
6954
  }
6565
- const coverage = scriptMembers.find((member) => memberName5(member) === "test:unit:coverage");
6955
+ const coverage = scriptMembers.find((member) => memberName6(member) === "test:unit:coverage");
6566
6956
  const coverageCommand = memberValue3(coverage);
6567
6957
  if (coverageCommand === void 0 || !/\bvitest\b/.test(coverageCommand) || !COVERAGE_FLAG_PATTERN.test(coverageCommand)) {
6568
6958
  context.report({
@@ -6570,7 +6960,7 @@ var vitestCoverageRule = {
6570
6960
  message: 'package.json must declare a "test:unit:coverage" script that runs Vitest with coverage.'
6571
6961
  });
6572
6962
  }
6573
- const configName = VITEST_CONFIG_NAMES.find((name) => existsSync5(path45.join(context.cwd, name)));
6963
+ const configName = VITEST_CONFIG_NAMES.find((name) => existsSync7(path47.join(context.cwd, name)));
6574
6964
  if (!configName) {
6575
6965
  context.report({
6576
6966
  node,
@@ -6578,7 +6968,7 @@ var vitestCoverageRule = {
6578
6968
  });
6579
6969
  return;
6580
6970
  }
6581
- const content = readFileSync10(path45.join(context.cwd, configName), "utf8");
6971
+ const content = readFileSync12(path47.join(context.cwd, configName), "utf8");
6582
6972
  for (const metric of THRESHOLD_METRICS) {
6583
6973
  if (!new RegExp(`\\b${metric}\\s*:\\s*[1-9]\\d*`).test(content)) {
6584
6974
  context.report({ node, message: `${configName} must set a coverage threshold above zero for ${metric}.` });
@@ -6590,7 +6980,7 @@ var vitestCoverageRule = {
6590
6980
  message: `${configName} must enable coverage.thresholds.autoUpdate with true or the monotonic 0.1-point buffered formatter.`
6591
6981
  });
6592
6982
  }
6593
- const stagedTests = scriptMembers.find((member) => memberName5(member) === "test:unit:staged");
6983
+ const stagedTests = scriptMembers.find((member) => memberName6(member) === "test:unit:staged");
6594
6984
  const stagedTestsCommand = memberValue3(stagedTests);
6595
6985
  if (stagedTestsCommand === void 0 || !/\bvitest\b/.test(stagedTestsCommand) || !RELATED_PATTERN.test(stagedTestsCommand) || COVERAGE_FLAG_PATTERN.test(stagedTestsCommand)) {
6596
6986
  context.report({
@@ -6598,9 +6988,9 @@ var vitestCoverageRule = {
6598
6988
  message: 'package.json must declare a "test:unit:staged" script that runs vitest related without coverage.'
6599
6989
  });
6600
6990
  }
6601
- const lintStaged = root.members.find((member) => memberName5(member) === "lint-staged");
6991
+ const lintStaged = root.members.find((member) => memberName6(member) === "lint-staged");
6602
6992
  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"))
6993
+ (member) => SOURCE_GLOB_PATTERN2.test(memberName6(member)) && stringValues2(member.value).some((command) => command.includes("npm run test:unit:staged"))
6604
6994
  );
6605
6995
  if (!hasStagedTests) {
6606
6996
  context.report({
@@ -6615,6 +7005,7 @@ var vitestCoverageRule = {
6615
7005
 
6616
7006
  // eslint/rules/package-json/index.ts
6617
7007
  var repoPackageJsonRules = {
7008
+ "ci-checks": ciChecksRule,
6618
7009
  "exact-version": exactVersionRule,
6619
7010
  "lint-setup": lintSetupRule,
6620
7011
  "vitest-coverage": vitestCoverageRule
@@ -6624,8 +7015,8 @@ var nextjsPackageJsonRules = {
6624
7015
  };
6625
7016
 
6626
7017
  // eslint/rules/prefer-enum.ts
6627
- import path46 from "path";
6628
- import ts9 from "typescript";
7018
+ import path48 from "path";
7019
+ import ts10 from "typescript";
6629
7020
  function isConstAssertion(node) {
6630
7021
  const typeAnnotation = node.typeAnnotation;
6631
7022
  return typeAnnotation?.type === "TSTypeReference" && typeAnnotation.typeName?.type === "Identifier" && typeAnnotation.typeName.name === "const";
@@ -6647,7 +7038,7 @@ function isZodCall(node, method) {
6647
7038
  const { callee } = node;
6648
7039
  return callee?.type === "MemberExpression" && !callee.computed && callee.object.type === "Identifier" && callee.object.name === "z" && callee.property.type === "Identifier" && callee.property.name === method;
6649
7040
  }
6650
- function propertyName4(property) {
7041
+ function propertyName5(property) {
6651
7042
  if (property.computed) return void 0;
6652
7043
  if (property.key.type === "Identifier") return property.key.name;
6653
7044
  if (property.key.type === "Literal" && typeof property.key.value === "string") return property.key.value;
@@ -6658,7 +7049,7 @@ function rawZodDiscriminantLiteral(schemaCall, discriminator) {
6658
7049
  const shape = schemaCall.arguments[0];
6659
7050
  if (shape?.type !== "ObjectExpression") return void 0;
6660
7051
  for (const property of shape.properties) {
6661
- if (property.type !== "Property" || propertyName4(property) !== discriminator) continue;
7052
+ if (property.type !== "Property" || propertyName5(property) !== discriminator) continue;
6662
7053
  if (property.value.type !== "CallExpression" || !isZodCall(property.value, "literal")) return void 0;
6663
7054
  const literal = property.value.arguments[0];
6664
7055
  if (literal?.type === "Literal" && (typeof literal.value === "string" || typeof literal.value === "number")) {
@@ -6679,13 +7070,13 @@ function isLiteralTupleAssertion(node) {
6679
7070
  return values.every((value) => value !== void 0) && new Set(values).size >= 2;
6680
7071
  }
6681
7072
  function isTsLiteralTupleDeclaration(declaration) {
6682
- if (!ts9.isVariableDeclaration(declaration) || !declaration.initializer) return false;
7073
+ if (!ts10.isVariableDeclaration(declaration) || !declaration.initializer) return false;
6683
7074
  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) {
7075
+ 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
7076
  return false;
6686
7077
  }
6687
7078
  const values = init.expression.elements.map(
6688
- (element) => ts9.isStringLiteral(element) || ts9.isNumericLiteral(element) ? element.text : void 0
7079
+ (element) => ts10.isStringLiteral(element) || ts10.isNumericLiteral(element) ? element.text : void 0
6689
7080
  );
6690
7081
  return values.every((value) => value !== void 0) && new Set(values).size >= 2;
6691
7082
  }
@@ -6698,9 +7089,9 @@ var preferEnumRule = {
6698
7089
  }
6699
7090
  },
6700
7091
  create(context) {
6701
- const filename = path46.resolve(context.filename);
7092
+ const filename = path48.resolve(context.filename);
6702
7093
  const sourceRoot = sourceRootOf(context);
6703
- if (!filename.startsWith(sourceRoot + path46.sep)) return {};
7094
+ if (!filename.startsWith(sourceRoot + path48.sep)) return {};
6704
7095
  const objectSchemas = /* @__PURE__ */ new Map();
6705
7096
  const literalTuples = /* @__PURE__ */ new Set();
6706
7097
  const enumTupleUses = [];
@@ -6714,7 +7105,7 @@ var preferEnumRule = {
6714
7105
  const checker = services.program.getTypeChecker();
6715
7106
  const symbol = checker.getSymbolAtLocation(tsNode);
6716
7107
  if (!symbol) return false;
6717
- const original = symbol.flags === ts9.SymbolFlags.Alias ? checker.getAliasedSymbol(symbol) : symbol;
7108
+ const original = symbol.flags === ts10.SymbolFlags.Alias ? checker.getAliasedSymbol(symbol) : symbol;
6718
7109
  return (original.declarations ?? []).some(isTsLiteralTupleDeclaration);
6719
7110
  }
6720
7111
  return {
@@ -6809,8 +7200,8 @@ var preferEnumRule = {
6809
7200
  };
6810
7201
 
6811
7202
  // eslint/rules/prefer-object-destructuring.ts
6812
- import ts10 from "typescript";
6813
- var DOC6 = "See docs/next-codebase-guide/rules/redundant-aliases-rule.md";
7203
+ import ts11 from "typescript";
7204
+ var DOC7 = "See docs/next-codebase-guide/rules/redundant-aliases-rule.md";
6814
7205
  function hasTypeAnnotation(identifier) {
6815
7206
  return "typeAnnotation" in identifier && identifier.typeAnnotation !== void 0;
6816
7207
  }
@@ -6822,19 +7213,19 @@ function directPropertyBinding(context, declarator, isEnumValue) {
6822
7213
  if (member.computed || member.optional || member.property.type !== "Identifier") return void 0;
6823
7214
  if (!memberCanBecomeLocal(member)) return void 0;
6824
7215
  if (context.sourceCode.getCommentsInside(declarator).length > 0) return void 0;
6825
- const propertyName5 = member.property.name;
7216
+ const propertyName6 = member.property.name;
6826
7217
  const localName = declarator.id.name;
6827
- if (propertyName5 !== localName) return void 0;
7218
+ if (propertyName6 !== localName) return void 0;
6828
7219
  const source = member.object;
6829
7220
  const sourceText = context.sourceCode.getText(source);
6830
7221
  return {
6831
7222
  declarator,
6832
7223
  member,
6833
- propertyName: propertyName5,
7224
+ propertyName: propertyName6,
6834
7225
  localName,
6835
7226
  source,
6836
7227
  sourceText,
6837
- bindingText: propertyName5
7228
+ bindingText: propertyName6
6838
7229
  };
6839
7230
  }
6840
7231
  function canGroupSource(source) {
@@ -6852,8 +7243,8 @@ function rootIdentifierName(node) {
6852
7243
  if (node.type !== "MemberExpression" || node.object.type === "Super") return void 0;
6853
7244
  return rootIdentifierName(node.object);
6854
7245
  }
6855
- function isCompliantLocalName(propertyName5) {
6856
- return !propertyName5.includes("_") || /^[A-Z][A-Z0-9]*(?:_[A-Z0-9]+)*$/u.test(propertyName5);
7246
+ function isCompliantLocalName(propertyName6) {
7247
+ return !propertyName6.includes("_") || /^[A-Z][A-Z0-9]*(?:_[A-Z0-9]+)*$/u.test(propertyName6);
6857
7248
  }
6858
7249
  function propertyNameOf(node) {
6859
7250
  if (node.type !== "Property" || node.computed) return void 0;
@@ -6902,8 +7293,8 @@ function enumValueResolver(context) {
6902
7293
  const checker = services.program.getTypeChecker();
6903
7294
  const { esTreeNodeToTSNodeMap: nodeMap } = services;
6904
7295
  const isEnumSymbol = (symbol) => {
6905
- const resolved = symbol.flags === ts10.SymbolFlags.Alias ? checker.getAliasedSymbol(symbol) : symbol;
6906
- return (resolved.declarations ?? []).some((declaration) => ts10.isEnumDeclaration(declaration));
7296
+ const resolved = symbol.flags === ts11.SymbolFlags.Alias ? checker.getAliasedSymbol(symbol) : symbol;
7297
+ return (resolved.declarations ?? []).some((declaration) => ts11.isEnumDeclaration(declaration));
6907
7298
  };
6908
7299
  return (node) => {
6909
7300
  const tsNode = nodeMap.get(node);
@@ -6919,27 +7310,27 @@ function detachableCallResolver(context) {
6919
7310
  if (!services) return () => false;
6920
7311
  const checker = services.program.getTypeChecker();
6921
7312
  const { esTreeNodeToTSNodeMap: nodeMap } = services;
6922
- const isUnboundFunctionType = (type) => ts10.isFunctionTypeNode(type) && !type.parameters.some((parameter) => ts10.isIdentifier(parameter.name) && parameter.name.text === "this");
7313
+ const isUnboundFunctionType = (type) => ts11.isFunctionTypeNode(type) && !type.parameters.some((parameter) => ts11.isIdentifier(parameter.name) && parameter.name.text === "this");
6923
7314
  return (member) => {
6924
7315
  const node = nodeMap.get(member);
6925
- if (!node || !ts10.isPropertyAccessExpression(node)) return false;
7316
+ if (!node || !ts11.isPropertyAccessExpression(node)) return false;
6926
7317
  const symbol = checker.getSymbolAtLocation(node.name);
6927
7318
  const declarations = symbol?.declarations;
6928
7319
  if (!declarations?.length) return false;
6929
7320
  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);
7321
+ if (ts11.isPropertySignature(declaration) || ts11.isPropertyDeclaration(declaration)) {
7322
+ return declaration.type !== void 0 && isUnboundFunctionType(declaration.type) || ts11.isPropertyDeclaration(declaration) && declaration.initializer !== void 0 && ts11.isArrowFunction(declaration.initializer);
6932
7323
  }
6933
- if (ts10.isPropertyAssignment(declaration)) return ts10.isArrowFunction(declaration.initializer);
7324
+ if (ts11.isPropertyAssignment(declaration)) return ts11.isArrowFunction(declaration.initializer);
6934
7325
  return false;
6935
7326
  });
6936
7327
  };
6937
7328
  }
6938
7329
  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);
7330
+ const mapping2 = renamedDirectMapping(context, member);
7331
+ if (!mapping2 || !ownershipResolver) return false;
7332
+ const sourceResolution = ownershipResolver.sourceMember(mapping2.sourceMember);
7333
+ const targetResolution = ownershipResolver.targetProperty(mapping2.property, mapping2.targetName);
6943
7334
  return sourceResolution.kind === "data-contract" || targetResolution.kind === "data-contract";
6944
7335
  }
6945
7336
  function memberCanBeDestructured(context, ownershipResolver, member, isEnumValue) {
@@ -6975,10 +7366,10 @@ function recordMemberUsage(context, scope, ownershipResolver, member, isEnumValu
6975
7366
  if (!isGroupedUsageSource(member.object) || !memberIsRead(context, member, detachableCall)) return;
6976
7367
  const sourceText = context.sourceCode.getText(member.object);
6977
7368
  const usage = objectUsage(scope, sourceText);
6978
- const propertyName5 = member.property.name;
6979
- usage.propertyNames.add(propertyName5);
7369
+ const propertyName6 = member.property.name;
7370
+ usage.propertyNames.add(propertyName6);
6980
7371
  if (!memberIsDirectVariableInitializer(context, member)) {
6981
- usage.directMembers.push({ member, propertyName: propertyName5 });
7372
+ usage.directMembers.push({ member, propertyName: propertyName6 });
6982
7373
  }
6983
7374
  }
6984
7375
  function recordDestructuringUsage(context, scope, declaration, isEnumValue) {
@@ -7001,7 +7392,7 @@ function recordDestructuringUsage(context, scope, declaration, isEnumValue) {
7001
7392
  }
7002
7393
  function scopeUsageMessage(sourceText, propertyNames) {
7003
7394
  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}`;
7395
+ return `${names} are read from "${sourceText}" in the same block. Destructure them together in one declaration. ${DOC7}`;
7005
7396
  }
7006
7397
  function hasBinding(context, node, name) {
7007
7398
  const initialScope = context.sourceCode.getScope(node);
@@ -7105,13 +7496,13 @@ function groupedDestructuringSelections(context, first, isEnumValue) {
7105
7496
  if (!previous || nextNode?.type !== "VariableDeclaration" || nextNode.kind !== first.declaration.kind) break;
7106
7497
  const next = destructuringSelection(context, nextNode, isEnumValue);
7107
7498
  if (next?.sourceText !== first.sourceText) break;
7108
- if (next.propertyNames.some((propertyName5) => seenProperties.has(propertyName5))) break;
7499
+ if (next.propertyNames.some((propertyName6) => seenProperties.has(propertyName6))) break;
7109
7500
  const [, previousEnd] = context.sourceCode.getRange(previous);
7110
7501
  const [nextStart] = context.sourceCode.getRange(nextNode);
7111
7502
  const gap = context.sourceCode.text.slice(previousEnd, nextStart);
7112
7503
  if (!whitespaceKeepsStatementsAdjacent(gap)) break;
7113
7504
  group.push(next);
7114
- for (const propertyName5 of next.propertyNames) seenProperties.add(propertyName5);
7505
+ for (const propertyName6 of next.propertyNames) seenProperties.add(propertyName6);
7115
7506
  }
7116
7507
  return group;
7117
7508
  }
@@ -7119,19 +7510,19 @@ function declarationTerminator(context, declaration) {
7119
7510
  return context.sourceCode.getText(declaration).trimEnd().endsWith(";") ? ";" : "";
7120
7511
  }
7121
7512
  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}`;
7513
+ 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
7514
  }
7124
7515
  function groupMessage(bindings) {
7125
7516
  const firstBinding = bindings[0];
7126
- if (!firstBinding) return `Use one object destructuring declaration. ${DOC6}`;
7517
+ if (!firstBinding) return `Use one object destructuring declaration. ${DOC7}`;
7127
7518
  const names = bindings.map(({ localName }) => `"${localName}"`).join(", ");
7128
- return `${names} are derived directly from properties of "${firstBinding.sourceText}". Use one object destructuring declaration. ${DOC6}`;
7519
+ return `${names} are derived directly from properties of "${firstBinding.sourceText}". Use one object destructuring declaration. ${DOC7}`;
7129
7520
  }
7130
7521
  function repeatedDestructuringMessage(group) {
7131
7522
  const first = group[0];
7132
- if (!first) return `Combine repeated destructuring into one declaration. ${DOC6}`;
7523
+ if (!first) return `Combine repeated destructuring into one declaration. ${DOC7}`;
7133
7524
  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}`;
7525
+ return `${names} destructure the same source "${first.sourceText}" repeatedly. Combine them into one object destructuring declaration. ${DOC7}`;
7135
7526
  }
7136
7527
  var preferObjectDestructuringRule = {
7137
7528
  meta: {
@@ -7165,9 +7556,9 @@ var preferObjectDestructuringRule = {
7165
7556
  const { member: firstDirectMember } = firstDirectUsage;
7166
7557
  const propertyNames = [...usage.propertyNames];
7167
7558
  const missingPropertyNames = propertyNames.filter(
7168
- (propertyName5) => !usage.destructuring?.propertyNames.has(propertyName5)
7559
+ (propertyName6) => !usage.destructuring?.propertyNames.has(propertyName6)
7169
7560
  );
7170
- if (missingPropertyNames.some((propertyName5) => hasBinding(context, firstDirectMember, propertyName5))) {
7561
+ if (missingPropertyNames.some((propertyName6) => hasBinding(context, firstDirectMember, propertyName6))) {
7171
7562
  continue;
7172
7563
  }
7173
7564
  context.report({
@@ -7181,7 +7572,7 @@ var preferObjectDestructuringRule = {
7181
7572
  return null;
7182
7573
  }
7183
7574
  const memberFixes = usage.directMembers.map(
7184
- ({ member, propertyName: propertyName5 }) => fixer.replaceText(member, propertyName5)
7575
+ ({ member, propertyName: propertyName6 }) => fixer.replaceText(member, propertyName6)
7185
7576
  );
7186
7577
  if (usage.destructuring) {
7187
7578
  if (missingPropertyNames.length === 0) return memberFixes;
@@ -7220,7 +7611,7 @@ ${indentation}`;
7220
7611
  continue;
7221
7612
  }
7222
7613
  if (fromSameSource.length > 1) {
7223
- const names = new Set(fromSameSource.map(({ propertyName: propertyName5 }) => propertyName5));
7614
+ const names = new Set(fromSameSource.map(({ propertyName: propertyName6 }) => propertyName6));
7224
7615
  if (names.size > 1) {
7225
7616
  context.report({ node: binding.node, message: scopeUsageMessage(binding.sourceText, names) });
7226
7617
  continue;
@@ -7249,7 +7640,7 @@ ${indentation}`;
7249
7640
  const sourceText = context.sourceCode.getText(declarator.init);
7250
7641
  context.report({
7251
7642
  node: declarator.id,
7252
- message: `"${sourceText}" is an enum. Keep enum member accesses qualified instead of destructuring it. ${DOC6}`
7643
+ message: `"${sourceText}" is an enum. Keep enum member accesses qualified instead of destructuring it. ${DOC7}`
7253
7644
  });
7254
7645
  }
7255
7646
  recordDestructuringUsage(context, currentUsageScope(), node, isEnumValue);
@@ -7260,12 +7651,12 @@ ${indentation}`;
7260
7651
  if (group.length <= 1) {
7261
7652
  if (node.kind === "const" && selection.propertyNames.length === 1 && supportsSinglePropertySource(selection.source)) {
7262
7653
  const declarator = node.declarations[0];
7263
- const propertyName5 = selection.propertyNames[0];
7264
- if (declarator && propertyName5) {
7654
+ const propertyName6 = selection.propertyNames[0];
7655
+ if (declarator && propertyName6) {
7265
7656
  currentUsageScope()?.singleProperties.push({
7266
7657
  node: declarator.id,
7267
7658
  sourceText: selection.sourceText,
7268
- propertyName: propertyName5
7659
+ propertyName: propertyName6
7269
7660
  });
7270
7661
  }
7271
7662
  }
@@ -7295,7 +7686,7 @@ ${indentation}`;
7295
7686
  if (bindings.length === 0) return;
7296
7687
  const firstBinding = bindings[0];
7297
7688
  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;
7689
+ 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
7690
  if (sameSourceBindings) {
7300
7691
  context.report({
7301
7692
  node,
@@ -7350,7 +7741,7 @@ ${indentation}`;
7350
7741
  };
7351
7742
 
7352
7743
  // eslint/rules/pure-function-extract.ts
7353
- import path47 from "path";
7744
+ import path49 from "path";
7354
7745
  var ROUTE_HANDLER_EXPORT_NAMES = /* @__PURE__ */ new Set([
7355
7746
  "GET",
7356
7747
  "POST",
@@ -7415,12 +7806,12 @@ var pureFunctionExtractRule = {
7415
7806
  },
7416
7807
  create(context) {
7417
7808
  const filename = context.filename;
7418
- const isRouteFile = path47.basename(filename) === "route.ts";
7809
+ const isRouteFile = path49.basename(filename) === "route.ts";
7419
7810
  const isComponentFile = filename.endsWith(".tsx") || filename.endsWith(".jsx");
7420
7811
  const sourceRoot = sourceRootOf(context);
7421
- const relative = path47.relative(sourceRoot, filename);
7812
+ const relative = path49.relative(sourceRoot, filename);
7422
7813
  if (relative.startsWith("..")) return {};
7423
- const segments = relative.split(path47.sep);
7814
+ const segments = relative.split(path49.sep);
7424
7815
  const folders = segments.slice(0, -1);
7425
7816
  const isHookSupportFile = folders.includes("hooks") && /\.(?:[cm]?[jt]s)$/.test(filename);
7426
7817
  if (!isComponentFile && !isRouteFile && !isHookSupportFile) return {};
@@ -7480,15 +7871,15 @@ var pureFunctionExtractRule = {
7480
7871
  };
7481
7872
 
7482
7873
  // eslint/rules/repeated-numeric-value.ts
7483
- import path48 from "path";
7874
+ import path50 from "path";
7484
7875
  function isNonProductionFile(file, sourceRoot) {
7485
- const relative = path48.relative(sourceRoot, file);
7486
- const segments = relative.split(path48.sep);
7487
- const basename = path48.basename(file);
7876
+ const relative = path50.relative(sourceRoot, file);
7877
+ const segments = relative.split(path50.sep);
7878
+ const basename = path50.basename(file);
7488
7879
  return /\.(?:test|spec|mock)\.[^.]+$/.test(basename) || segments.some((segment) => segment === "__tests__" || segment === "__mocks__" || segment === "mocks");
7489
7880
  }
7490
7881
  function isCanonicalConstantFile(file, sourceRoot) {
7491
- const segments = path48.relative(sourceRoot, file).split(path48.sep);
7882
+ const segments = path50.relative(sourceRoot, file).split(path50.sep);
7492
7883
  return segments.includes("constants") || segments[0] === "config";
7493
7884
  }
7494
7885
  function groupKey(literal) {
@@ -7504,7 +7895,7 @@ var repeatedNumericValueRule = {
7504
7895
  },
7505
7896
  create(context) {
7506
7897
  const sourceRoot = sourceRootOf(context);
7507
- const file = path48.resolve(context.filename);
7898
+ const file = path50.resolve(context.filename);
7508
7899
  if (isNonProductionFile(file, sourceRoot) || isCanonicalConstantFile(file, sourceRoot)) return {};
7509
7900
  const index = getProjectIndex(sourceRoot);
7510
7901
  if (!index) return {};
@@ -7541,11 +7932,11 @@ var repeatedNumericValueRule = {
7541
7932
  };
7542
7933
 
7543
7934
  // eslint/rules/repeated-semantic-literal.ts
7544
- import path50 from "path";
7935
+ import path52 from "path";
7545
7936
 
7546
7937
  // eslint/rules/imported-enum-literals.ts
7547
- import path49 from "path";
7548
- import ts11 from "typescript";
7938
+ import path51 from "path";
7939
+ import ts12 from "typescript";
7549
7940
  var columnMethods2 = /* @__PURE__ */ new Set([
7550
7941
  "eq",
7551
7942
  "neq",
@@ -7561,13 +7952,13 @@ var columnMethods2 = /* @__PURE__ */ new Set([
7561
7952
  "filter",
7562
7953
  "not"
7563
7954
  ]);
7564
- function memberName6(name) {
7565
- if (ts11.isIdentifier(name) || ts11.isStringLiteral(name)) return name.text;
7955
+ function memberName7(name) {
7956
+ if (ts12.isIdentifier(name) || ts12.isStringLiteral(name)) return name.text;
7566
7957
  return void 0;
7567
7958
  }
7568
7959
  function isWithin3(root, file) {
7569
- const relative = path49.relative(root, file);
7570
- return relative === "" || !relative.startsWith("..") && !path49.isAbsolute(relative);
7960
+ const relative = path51.relative(root, file);
7961
+ return relative === "" || !relative.startsWith("..") && !path51.isAbsolute(relative);
7571
7962
  }
7572
7963
  function domainOf(name) {
7573
7964
  if (name.endsWith("ColumnEnum")) return "column";
@@ -7577,23 +7968,23 @@ function domainOf(name) {
7577
7968
  function importedEnums(file, checker, sourceRoot, importedNames) {
7578
7969
  const matches = /* @__PURE__ */ new Map();
7579
7970
  for (const statement of file.statements) {
7580
- if (!ts11.isImportDeclaration(statement) || !statement.importClause?.namedBindings || !ts11.isNamedImports(statement.importClause.namedBindings)) {
7971
+ if (!ts12.isImportDeclaration(statement) || !statement.importClause?.namedBindings || !ts12.isNamedImports(statement.importClause.namedBindings)) {
7581
7972
  continue;
7582
7973
  }
7583
7974
  for (const specifier of statement.importClause.namedBindings.elements) {
7584
7975
  if (!importedNames.has(specifier.name.text)) continue;
7585
7976
  const symbol = checker.getSymbolAtLocation(specifier.name);
7586
7977
  if (!symbol) continue;
7587
- const resolved = symbol.flags === ts11.SymbolFlags.Alias ? checker.getAliasedSymbol(symbol) : symbol;
7978
+ const resolved = symbol.flags === ts12.SymbolFlags.Alias ? checker.getAliasedSymbol(symbol) : symbol;
7588
7979
  for (const declaration of resolved.declarations ?? []) {
7589
- if (!ts11.isEnumDeclaration(declaration)) continue;
7590
- const declarationFile = path49.resolve(declaration.getSourceFile().fileName);
7980
+ if (!ts12.isEnumDeclaration(declaration)) continue;
7981
+ const declarationFile = path51.resolve(declaration.getSourceFile().fileName);
7591
7982
  if (!isWithin3(sourceRoot, declarationFile)) continue;
7592
7983
  const domain = domainOf(declaration.name.text);
7593
7984
  if (!domain) continue;
7594
7985
  for (const member of declaration.members) {
7595
- if (!member.initializer || !ts11.isStringLiteral(member.initializer)) continue;
7596
- const name = memberName6(member.name);
7986
+ if (!member.initializer || !ts12.isStringLiteral(member.initializer)) continue;
7987
+ const name = memberName7(member.name);
7597
7988
  if (!name) continue;
7598
7989
  const entries = matches.get(member.initializer.text) ?? [];
7599
7990
  entries.push({
@@ -7609,25 +8000,25 @@ function importedEnums(file, checker, sourceRoot, importedNames) {
7609
8000
  return matches;
7610
8001
  }
7611
8002
  function isPathname2(node) {
7612
- return ts11.isPropertyAccessExpression(node) && node.name.text === "pathname";
8003
+ return ts12.isPropertyAccessExpression(node) && node.name.text === "pathname";
7613
8004
  }
7614
8005
  function domainForUse(node) {
7615
8006
  const parent = node.parent;
7616
- if (ts11.isPropertyAssignment(parent) && parent.initializer === node && memberName6(parent.name) === "path") {
8007
+ if (ts12.isPropertyAssignment(parent) && parent.initializer === node && memberName7(parent.name) === "path") {
7617
8008
  return "route";
7618
8009
  }
7619
- if (ts11.isCallExpression(parent) && parent.arguments[0] === node && ts11.isPropertyAccessExpression(parent.expression)) {
8010
+ if (ts12.isCallExpression(parent) && parent.arguments[0] === node && ts12.isPropertyAccessExpression(parent.expression)) {
7620
8011
  const { expression, name } = parent.expression;
7621
8012
  if (columnMethods2.has(name.text)) return "column";
7622
8013
  if (name.text === "startsWith" && isPathname2(expression)) return "route";
7623
8014
  }
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))) {
8015
+ 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
8016
  return "route";
7626
8017
  }
7627
8018
  return void 0;
7628
8019
  }
7629
8020
  function importedEnumLiteralUses(context, root) {
7630
- const filename = path49.resolve(context.filename);
8021
+ const filename = path51.resolve(context.filename);
7631
8022
  if (!isWithin3(root, filename)) return [];
7632
8023
  const services = typedParserServices(context.sourceCode.parserServices);
7633
8024
  if (!services) return [];
@@ -7643,7 +8034,7 @@ function importedEnumLiteralUses(context, root) {
7643
8034
  if (matches.size === 0) return [];
7644
8035
  const uses = [];
7645
8036
  const visit = (node) => {
7646
- if (ts11.isStringLiteral(node)) {
8037
+ if (ts12.isStringLiteral(node)) {
7647
8038
  const domain = domainForUse(node);
7648
8039
  const candidates = matches.get(node.text)?.filter((entry) => entry.domain === domain) ?? [];
7649
8040
  if (candidates.length === 1) {
@@ -7660,14 +8051,14 @@ function importedEnumLiteralUses(context, root) {
7660
8051
  }
7661
8052
  }
7662
8053
  }
7663
- ts11.forEachChild(node, visit);
8054
+ ts12.forEachChild(node, visit);
7664
8055
  };
7665
8056
  visit(file);
7666
8057
  return uses;
7667
8058
  }
7668
8059
 
7669
8060
  // eslint/rules/repeated-semantic-literal.ts
7670
- var DOC7 = "See docs/next-codebase-guide/rules/constants-rule.md";
8061
+ var DOC8 = "See docs/next-codebase-guide/rules/constants-rule.md";
7671
8062
  var closedDomainFamilies = /* @__PURE__ */ new Set(["api-route", "event", "storage"]);
7672
8063
  function canonicalMatches(use, canonical, sourceRoot) {
7673
8064
  if (use.kind !== canonical.kind || use.value !== canonical.value) return false;
@@ -7681,7 +8072,7 @@ function canonicalMatches(use, canonical, sourceRoot) {
7681
8072
  const semanticName2 = use.family.split(":")[1];
7682
8073
  if (!semanticName2 || !name.toLowerCase().includes(semanticName2.toLowerCase())) return false;
7683
8074
  const location = featureOf(canonical.file, sourceRoot);
7684
- return location === featureOf(use.file, sourceRoot) || path50.relative(sourceRoot, canonical.file).split(path50.sep)[0] === "constants";
8075
+ return location === featureOf(use.file, sourceRoot) || path52.relative(sourceRoot, canonical.file).split(path52.sep)[0] === "constants";
7685
8076
  }
7686
8077
  return false;
7687
8078
  }
@@ -7695,14 +8086,14 @@ function messageFor(use, matches, duplicateRouteDomains, existingRouteEnum, root
7695
8086
  const count = new Set(matches.map((match) => match.file)).size;
7696
8087
  const kind = use.kind === "string" ? "string" : "numeric";
7697
8088
  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}`;
8089
+ const location = path52.relative(root, existingRouteEnum.file).replaceAll(path52.sep, "/");
8090
+ return `The route ${formatValue(use)} repeats; add a member to existing ${existingRouteEnum.owner} in src/${location} and reuse it. ${DOC8}`;
7700
8091
  }
7701
8092
  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}`;
8093
+ return `The ${kind} literal ${formatValue(use)} repeats in the same semantic role in this file. Extract a file-local const. ${DOC8}`;
7703
8094
  }
7704
8095
  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}`;
8096
+ 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
8097
  }
7707
8098
  var repeatedSemanticLiteralRule = {
7708
8099
  meta: {
@@ -7714,7 +8105,7 @@ var repeatedSemanticLiteralRule = {
7714
8105
  },
7715
8106
  create(context) {
7716
8107
  const root = sourceRootOf(context);
7717
- const file = path50.resolve(context.filename);
8108
+ const file = path52.resolve(context.filename);
7718
8109
  if (!isProductionSource(file, root)) return {};
7719
8110
  const project = getProjectIndex(root);
7720
8111
  if (!project?.modules.has(file)) return {};
@@ -7759,11 +8150,11 @@ var repeatedSemanticLiteralRule = {
7759
8150
  return {
7760
8151
  Program(node) {
7761
8152
  for (const use of imported) {
7762
- const relative = path50.relative(root, use.sourceFile).replaceAll(path50.sep, "/");
8153
+ const relative = path52.relative(root, use.sourceFile).replaceAll(path52.sep, "/");
7763
8154
  context.report({
7764
8155
  node,
7765
8156
  loc: { line: use.line, column: use.column },
7766
- message: `Reuse ${use.reference} from src/${relative} instead of raw ${JSON.stringify(use.value)}. ${DOC7}`
8157
+ message: `Reuse ${use.reference} from src/${relative} instead of raw ${JSON.stringify(use.value)}. ${DOC8}`
7767
8158
  });
7768
8159
  }
7769
8160
  for (const use of current) {
@@ -7774,11 +8165,11 @@ var repeatedSemanticLiteralRule = {
7774
8165
  if (candidates.length === 1) {
7775
8166
  const canonical = candidates[0];
7776
8167
  if (!canonical) continue;
7777
- const relative = path50.relative(root, canonical.file).replaceAll(path50.sep, "/");
8168
+ const relative = path52.relative(root, canonical.file).replaceAll(path52.sep, "/");
7778
8169
  context.report({
7779
8170
  node,
7780
8171
  loc: { line: use.line, column: use.column },
7781
- message: `Reuse ${canonicalName(canonical)} from src/${relative} instead of raw ${formatValue(use)}. ${DOC7}`
8172
+ message: `Reuse ${canonicalName(canonical)} from src/${relative} instead of raw ${formatValue(use)}. ${DOC8}`
7782
8173
  });
7783
8174
  continue;
7784
8175
  }
@@ -7787,11 +8178,11 @@ var repeatedSemanticLiteralRule = {
7787
8178
  const peers = groups.get(key) ?? [];
7788
8179
  if (peers.length < 2) {
7789
8180
  if (use.family === "api-route" && existingRouteEnum?.owner) {
7790
- const location = path50.relative(root, existingRouteEnum.file).replaceAll(path50.sep, "/");
8181
+ const location = path52.relative(root, existingRouteEnum.file).replaceAll(path52.sep, "/");
7791
8182
  context.report({
7792
8183
  node,
7793
8184
  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}`
8185
+ message: `The route ${formatValue(use)} belongs to existing ${existingRouteEnum.owner}; add a member in src/${location} and reuse it. ${DOC8}`
7795
8186
  });
7796
8187
  continue;
7797
8188
  }
@@ -7800,7 +8191,7 @@ var repeatedSemanticLiteralRule = {
7800
8191
  context.report({
7801
8192
  node,
7802
8193
  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}`
8194
+ 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
8195
  });
7805
8196
  }
7806
8197
  continue;
@@ -7999,7 +8390,7 @@ var repeatedStructureRule = {
7999
8390
 
8000
8391
  // eslint/rules/require-barrel-star-exports.ts
8001
8392
  import fs5 from "fs";
8002
- import path51 from "path";
8393
+ import path53 from "path";
8003
8394
  var SUPPORT_FOLDERS3 = /* @__PURE__ */ new Set(["constants", "types", "schemas"]);
8004
8395
  var INDEX_NAMES = /* @__PURE__ */ new Set(["index.ts", "index.tsx", "index.mts", "index.cts"]);
8005
8396
  var MODULE_EXTENSIONS3 = [".ts", ".tsx", ".mts", ".cts", ".js", ".jsx", ".mjs", ".cjs"];
@@ -8007,9 +8398,9 @@ function resolveSiblingModule(indexFile, specifier) {
8007
8398
  if (!specifier.startsWith("./")) return void 0;
8008
8399
  const relative = specifier.slice(2);
8009
8400
  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}`);
8401
+ const directory = path53.dirname(indexFile);
8402
+ const direct = path53.resolve(directory, relative);
8403
+ const candidates = path53.extname(direct) ? [direct] : MODULE_EXTENSIONS3.map((extension) => `${direct}${extension}`);
8013
8404
  return candidates.find((candidate) => fs5.existsSync(candidate) && fs5.statSync(candidate).isFile());
8014
8405
  }
8015
8406
  var requireBarrelStarExportsRule = {
@@ -8022,9 +8413,9 @@ var requireBarrelStarExportsRule = {
8022
8413
  fixable: "code"
8023
8414
  },
8024
8415
  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 {};
8416
+ const filename = path53.resolve(context.filename);
8417
+ if (!INDEX_NAMES.has(path53.basename(filename))) return {};
8418
+ if (!SUPPORT_FOLDERS3.has(path53.basename(path53.dirname(filename)))) return {};
8028
8419
  return {
8029
8420
  ExportNamedDeclaration(node) {
8030
8421
  const sourceNode = node.source;
@@ -8077,7 +8468,7 @@ var requireBarrelStarExportsRule = {
8077
8468
  };
8078
8469
 
8079
8470
  // eslint/rules/root-support-placement.ts
8080
- import path52 from "path";
8471
+ import path54 from "path";
8081
8472
  function isSupportFolder(value) {
8082
8473
  return value === "utils" || value === "types" || value === "schemas" || value === "constants";
8083
8474
  }
@@ -8110,7 +8501,7 @@ var rootSupportPlacementRule = {
8110
8501
  },
8111
8502
  create(context) {
8112
8503
  const sourceRoot = sourceRootOf(context);
8113
- const file = path52.resolve(context.filename);
8504
+ const file = path54.resolve(context.filename);
8114
8505
  const segments = segmentsOf(file, sourceRoot);
8115
8506
  const folderSegments = folderSegmentsOf(file, sourceRoot);
8116
8507
  const supportFolder = folderSegments[folderSegments.length - 1];
@@ -8156,8 +8547,104 @@ var rootSupportPlacementRule = {
8156
8547
  };
8157
8548
 
8158
8549
  // eslint/rules/route-handler-shape.ts
8159
- import path53 from "path";
8160
- import ts12 from "typescript";
8550
+ import path56 from "path";
8551
+ import ts13 from "typescript";
8552
+
8553
+ // eslint/rules/route-single-use-delegation.ts
8554
+ import path55 from "path";
8555
+ function responseCall(expression) {
8556
+ if (!expression) return void 0;
8557
+ if (expression.type === "AwaitExpression") return responseCall(expression.argument);
8558
+ if (expression.type === "CallExpression" && expression.callee.type === "Identifier") return expression;
8559
+ if (expression.type !== "ObjectExpression") return void 0;
8560
+ const dataProperties = expression.properties.filter(
8561
+ (property) => property.type === "Property" && !property.computed && (property.key.type === "Identifier" && property.key.name === "data" || property.key.type === "Literal" && property.key.value === "data")
8562
+ );
8563
+ if (dataProperties.length !== 1) return void 0;
8564
+ const otherProperties = expression.properties.filter((property) => !dataProperties.includes(property));
8565
+ if (otherProperties.some(
8566
+ (property) => property.type !== "Property" || property.value.type !== "Literal" || property.computed
8567
+ )) {
8568
+ return void 0;
8569
+ }
8570
+ return responseCall(dataProperties[0]?.type === "Property" ? dataProperties[0].value : void 0);
8571
+ }
8572
+ function soleDelegation(handler) {
8573
+ if (handler.body.type !== "BlockStatement") return responseCall(handler.body);
8574
+ const statements = handler.body.body;
8575
+ if (statements.length === 1 && statements[0]?.type === "ReturnStatement") {
8576
+ return responseCall(statements[0].argument);
8577
+ }
8578
+ const [declaration, returned] = statements;
8579
+ if (statements.length !== 2 || declaration?.type !== "VariableDeclaration" || declaration.declarations.length !== 1 || returned?.type !== "ReturnStatement") {
8580
+ return void 0;
8581
+ }
8582
+ const variable = declaration.declarations[0];
8583
+ if (variable?.id.type !== "Identifier") return void 0;
8584
+ const call = responseCall(variable.init);
8585
+ if (!call || !returned.argument) return void 0;
8586
+ if (returned.argument.type === "Identifier" && returned.argument.name === variable.id.name) return call;
8587
+ if (returned.argument.type !== "ObjectExpression") return void 0;
8588
+ const properties = returned.argument.properties;
8589
+ if (properties.length !== 1 || properties[0]?.type !== "Property") return void 0;
8590
+ const property = properties[0];
8591
+ const key = property.key;
8592
+ const isData = !property.computed && (key.type === "Identifier" && key.name === "data" || key.type === "Literal" && key.value === "data");
8593
+ return isData && property.value.type === "Identifier" && property.value.name === variable.id.name ? call : void 0;
8594
+ }
8595
+ function isTestFile2(file) {
8596
+ return /(?:\.test|\.spec)\.[cm]?[jt]sx?$/.test(file) || path55.normalize(file).split(path55.sep).includes("__tests__");
8597
+ }
8598
+ function functionSource(index, file, name, sourceRoot, visited = /* @__PURE__ */ new Set()) {
8599
+ if (visited.has(file)) return void 0;
8600
+ visited.add(file);
8601
+ const module = index.modules.get(file);
8602
+ if (!module) return void 0;
8603
+ if (module.exports.some((entry) => entry.name === name && entry.kind === "function")) return file;
8604
+ if (!module.exports.some((entry) => entry.name === name) && !module.reexports.some((entry) => entry.names.length === 0)) {
8605
+ return void 0;
8606
+ }
8607
+ for (const entry of module.reexports) {
8608
+ if (entry.names.length > 0 && !entry.names.includes(name)) continue;
8609
+ const target = resolveSpecifier(file, entry.specifier, sourceRoot);
8610
+ if (!target) continue;
8611
+ const original = functionSource(index, target, name, sourceRoot, visited);
8612
+ if (original) return original;
8613
+ }
8614
+ return void 0;
8615
+ }
8616
+ function singleUseResponseDelegate(context, handler) {
8617
+ const call = soleDelegation(handler);
8618
+ if (call?.callee.type !== "Identifier") return void 0;
8619
+ const name = call.callee.name;
8620
+ const sourceRoot = sourceRootOf(context);
8621
+ const index = getProjectIndex(sourceRoot);
8622
+ if (!index) return void 0;
8623
+ for (const statement of context.sourceCode.ast.body) {
8624
+ if (statement.type !== "ImportDeclaration" || typeof statement.source.value !== "string") continue;
8625
+ const target = resolveSpecifier(context.filename, statement.source.value, sourceRoot);
8626
+ if (target === void 0 || target === context.filename) continue;
8627
+ for (const specifier of statement.specifiers) {
8628
+ if (specifier.type !== "ImportSpecifier" || specifier.local.name !== name) continue;
8629
+ const original = specifier.imported.type === "Identifier" ? specifier.imported.name : String(specifier.imported.value);
8630
+ const source = functionSource(index, target, original, sourceRoot);
8631
+ if (!source) continue;
8632
+ const bindings = context.sourceCode.getDeclaredVariables(specifier);
8633
+ if (!bindings.some((binding) => binding.references.length === 1)) continue;
8634
+ const consumers = index.symbolConsumers.get(symbolKey(source, original));
8635
+ if (!consumers?.has(context.filename)) continue;
8636
+ const activeConsumers = [...consumers].filter((consumer) => {
8637
+ if (isTestFile2(consumer)) return false;
8638
+ const module = index.modules.get(consumer);
8639
+ return !(module && module.reexports.length > 0 && module.imports.length === module.reexports.length && module.exports.every((entry) => entry.kind === "other"));
8640
+ });
8641
+ if (activeConsumers.length === 1 && activeConsumers[0] === context.filename) return original;
8642
+ }
8643
+ }
8644
+ return void 0;
8645
+ }
8646
+
8647
+ // eslint/rules/route-handler-shape.ts
8161
8648
  var HTTP_METHODS2 = /* @__PURE__ */ new Set(["GET", "POST", "PUT", "PATCH", "DELETE", "HEAD", "OPTIONS"]);
8162
8649
  var REQUIRED_BOUNDARY = "withResponse";
8163
8650
  function isFunctionLike(node) {
@@ -8175,33 +8662,33 @@ function findHandler(node) {
8175
8662
  return void 0;
8176
8663
  }
8177
8664
  function isLoop(node) {
8178
- return ts12.isForStatement(node) || ts12.isForOfStatement(node) || ts12.isForInStatement(node) || ts12.isWhileStatement(node) || ts12.isDoStatement(node);
8665
+ return ts13.isForStatement(node) || ts13.isForOfStatement(node) || ts13.isForInStatement(node) || ts13.isWhileStatement(node) || ts13.isDoStatement(node);
8179
8666
  }
8180
8667
  function isFunctionBoundary(node) {
8181
- return ts12.isFunctionExpression(node) || ts12.isArrowFunction(node) || ts12.isFunctionDeclaration(node);
8668
+ return ts13.isFunctionExpression(node) || ts13.isArrowFunction(node) || ts13.isFunctionDeclaration(node);
8182
8669
  }
8183
8670
  function analyzeHandlerBody(body, sourceText) {
8184
8671
  const start = body.range?.[0] ?? 0;
8185
8672
  const end = body.range?.[1] ?? sourceText.length;
8186
- const sourceFile = ts12.createSourceFile(
8673
+ const sourceFile = ts13.createSourceFile(
8187
8674
  "route.ts",
8188
8675
  sourceText.slice(start, end),
8189
- ts12.ScriptTarget.Latest,
8676
+ ts13.ScriptTarget.Latest,
8190
8677
  true,
8191
- ts12.ScriptKind.TS
8678
+ ts13.ScriptKind.TS
8192
8679
  );
8193
8680
  const kinds = /* @__PURE__ */ new Set();
8194
8681
  const calledNames = /* @__PURE__ */ new Set();
8195
8682
  const visit = (node) => {
8196
- if (ts12.isTryStatement(node)) kinds.add("try");
8683
+ if (ts13.isTryStatement(node)) kinds.add("try");
8197
8684
  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") {
8685
+ if (ts13.isIfStatement(node)) kinds.add("if");
8686
+ if (ts13.isCallExpression(node) && ts13.isPropertyAccessExpression(node.expression) && node.expression.name.text === "map") {
8200
8687
  kinds.add("map");
8201
8688
  }
8202
- if (ts12.isCallExpression(node) && ts12.isIdentifier(node.expression)) calledNames.add(node.expression.text);
8689
+ if (ts13.isCallExpression(node) && ts13.isIdentifier(node.expression)) calledNames.add(node.expression.text);
8203
8690
  if (isFunctionBoundary(node)) return;
8204
- ts12.forEachChild(node, visit);
8691
+ ts13.forEachChild(node, visit);
8205
8692
  };
8206
8693
  visit(sourceFile);
8207
8694
  return { kinds, calledNames };
@@ -8241,7 +8728,7 @@ var routeHandlerShapeRule = {
8241
8728
  }
8242
8729
  },
8243
8730
  create(context) {
8244
- if (path53.basename(context.filename) !== "route.ts") return {};
8731
+ if (path56.basename(context.filename) !== "route.ts") return {};
8245
8732
  const sourceText = context.sourceCode.text;
8246
8733
  function reportUnwrapped(node, name) {
8247
8734
  context.report({
@@ -8264,6 +8751,13 @@ var routeHandlerShapeRule = {
8264
8751
  });
8265
8752
  return;
8266
8753
  }
8754
+ const singleUseDelegate = singleUseResponseDelegate(context, handler);
8755
+ if (singleUseDelegate) {
8756
+ context.report({
8757
+ node,
8758
+ 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`
8759
+ });
8760
+ }
8267
8761
  const { kinds, calledNames } = analyzeHandlerBody(handler.body, sourceText);
8268
8762
  for (const kind of kinds) {
8269
8763
  context.report({
@@ -8300,7 +8794,7 @@ var routeHandlerShapeRule = {
8300
8794
  };
8301
8795
 
8302
8796
  // eslint/rules/schema-casing.ts
8303
- import path54 from "path";
8797
+ import path57 from "path";
8304
8798
  function isCamelCase(name) {
8305
8799
  return /^[a-z][a-zA-Z0-9]*$/.test(name);
8306
8800
  }
@@ -8328,9 +8822,9 @@ var schemaCasingRule = {
8328
8822
  }
8329
8823
  },
8330
8824
  create(context) {
8331
- const filename = path54.resolve(context.filename);
8825
+ const filename = path57.resolve(context.filename);
8332
8826
  const sourceRoot = sourceRootOf(context);
8333
- if (!filename.startsWith(sourceRoot + path54.sep)) return {};
8827
+ if (!filename.startsWith(sourceRoot + path57.sep)) return {};
8334
8828
  let zodLocalName;
8335
8829
  return {
8336
8830
  ImportDeclaration(node) {
@@ -8362,39 +8856,39 @@ var schemaCasingRule = {
8362
8856
  };
8363
8857
 
8364
8858
  // eslint/rules/sole-state-owner.ts
8365
- import path55 from "path";
8366
- import ts13 from "typescript";
8859
+ import path58 from "path";
8860
+ import ts14 from "typescript";
8367
8861
  function findStateHooks(node) {
8368
8862
  const hooks = [];
8369
8863
  const visit = (child) => {
8370
- if (ts13.isCallExpression(child) && ts13.isIdentifier(child.expression) && child.expression.text === "useState") {
8371
- if (ts13.isVariableDeclaration(child.parent)) {
8864
+ if (ts14.isCallExpression(child) && ts14.isIdentifier(child.expression) && child.expression.text === "useState") {
8865
+ if (ts14.isVariableDeclaration(child.parent)) {
8372
8866
  const { name } = child.parent;
8373
- if (ts13.isArrayBindingPattern(name) && name.elements.length >= 2) {
8867
+ if (ts14.isArrayBindingPattern(name) && name.elements.length >= 2) {
8374
8868
  const value = name.elements[0];
8375
8869
  const updater = name.elements[1];
8376
- if (value && updater && ts13.isBindingElement(value) && ts13.isBindingElement(updater)) {
8870
+ if (value && updater && ts14.isBindingElement(value) && ts14.isBindingElement(updater)) {
8377
8871
  const valueName = value.name;
8378
8872
  const updaterName = updater.name;
8379
- if (ts13.isIdentifier(valueName) && ts13.isIdentifier(updaterName)) {
8873
+ if (ts14.isIdentifier(valueName) && ts14.isIdentifier(updaterName)) {
8380
8874
  hooks.push({ value: valueName.text, updater: updaterName.text });
8381
8875
  }
8382
8876
  }
8383
8877
  }
8384
8878
  }
8385
8879
  }
8386
- ts13.forEachChild(child, visit);
8880
+ ts14.forEachChild(child, visit);
8387
8881
  };
8388
8882
  visit(node);
8389
8883
  return hooks;
8390
8884
  }
8391
8885
  function isHookUsage(node, hook) {
8392
- if (ts13.isCallExpression(node) && ts13.isIdentifier(node.expression) && node.expression.text === hook.updater) {
8886
+ if (ts14.isCallExpression(node) && ts14.isIdentifier(node.expression) && node.expression.text === hook.updater) {
8393
8887
  return "updater";
8394
8888
  }
8395
- if (ts13.isIdentifier(node) && node.text === hook.value) {
8889
+ if (ts14.isIdentifier(node) && node.text === hook.value) {
8396
8890
  const parent = node.parent;
8397
- if (ts13.isBindingElement(parent) || ts13.isPropertyAccessExpression(parent) || ts13.isShorthandPropertyAssignment(parent)) {
8891
+ if (ts14.isBindingElement(parent) || ts14.isPropertyAccessExpression(parent) || ts14.isShorthandPropertyAssignment(parent)) {
8398
8892
  return void 0;
8399
8893
  }
8400
8894
  return "value";
@@ -8404,16 +8898,16 @@ function isHookUsage(node, hook) {
8404
8898
  function topLevelJsxChildren(initial) {
8405
8899
  if (!initial) return void 0;
8406
8900
  let expression = initial;
8407
- while (ts13.isParenthesizedExpression(expression)) expression = expression.expression;
8408
- if (ts13.isJsxFragment(expression)) {
8901
+ while (ts14.isParenthesizedExpression(expression)) expression = expression.expression;
8902
+ if (ts14.isJsxFragment(expression)) {
8409
8903
  const children = expression.children.filter(
8410
- (c) => !ts13.isJsxText(c) && !ts13.isJsxSpreadAttribute(c)
8904
+ (c) => !ts14.isJsxText(c) && !ts14.isJsxSpreadAttribute(c)
8411
8905
  );
8412
8906
  return { root: expression, children };
8413
8907
  }
8414
- if (ts13.isJsxElement(expression)) {
8908
+ if (ts14.isJsxElement(expression)) {
8415
8909
  const children = expression.children.filter(
8416
- (c) => !ts13.isJsxText(c) && !ts13.isJsxSpreadAttribute(c)
8910
+ (c) => !ts14.isJsxText(c) && !ts14.isJsxSpreadAttribute(c)
8417
8911
  );
8418
8912
  return { root: expression, children };
8419
8913
  }
@@ -8427,8 +8921,8 @@ function collectUsesIn(child, hook) {
8427
8921
  positions.push(node);
8428
8922
  count += 1;
8429
8923
  }
8430
- if (ts13.isFunctionDeclaration(node) || ts13.isClassDeclaration(node)) return;
8431
- ts13.forEachChild(node, visit);
8924
+ if (ts14.isFunctionDeclaration(node) || ts14.isClassDeclaration(node)) return;
8925
+ ts14.forEachChild(node, visit);
8432
8926
  };
8433
8927
  visit(child);
8434
8928
  return { positions, count };
@@ -8442,7 +8936,7 @@ var soleStateOwnerRule = {
8442
8936
  }
8443
8937
  },
8444
8938
  create(context) {
8445
- const filename = path55.resolve(context.filename);
8939
+ const filename = path58.resolve(context.filename);
8446
8940
  if (!filename.endsWith(".tsx") && !filename.endsWith(".jsx")) return {};
8447
8941
  const text = context.sourceCode.text;
8448
8942
  const components = parseComponentInfo(text, filename);
@@ -8467,18 +8961,18 @@ var soleStateOwnerRule = {
8467
8961
  }
8468
8962
  };
8469
8963
  function analyzeSoleOwner(declaration, hook) {
8470
- const body = ts13.isFunctionDeclaration(declaration) ? declaration.body : void 0;
8471
- if (!body || !ts13.isBlock(body)) return void 0;
8964
+ const body = ts14.isFunctionDeclaration(declaration) ? declaration.body : void 0;
8965
+ if (!body || !ts14.isBlock(body)) return void 0;
8472
8966
  const returns = [];
8473
8967
  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);
8968
+ if (node !== body && (ts14.isFunctionLike(node) || ts14.isClassLike(node))) return;
8969
+ if (ts14.isReturnStatement(node)) returns.push(node);
8970
+ ts14.forEachChild(node, visit);
8477
8971
  };
8478
8972
  visit(body);
8479
8973
  if (returns.length !== 1) return void 0;
8480
8974
  const single = returns[0];
8481
- if (!single?.expression || !ts13.isExpression(single.expression)) return void 0;
8975
+ if (!single?.expression || !ts14.isExpression(single.expression)) return void 0;
8482
8976
  const returnExpression = single.expression;
8483
8977
  const root = topLevelJsxChildren(returnExpression);
8484
8978
  if (!root || root.children.length === 0) return void 0;
@@ -8501,11 +8995,11 @@ function usesOutsideJsx(declaration, hook, children) {
8501
8995
  let outside = false;
8502
8996
  const visit = (node) => {
8503
8997
  if (outside) return;
8504
- if (node !== declaration && (ts13.isFunctionDeclaration(node) || ts13.isClassDeclaration(node))) return;
8998
+ if (node !== declaration && (ts14.isFunctionDeclaration(node) || ts14.isClassDeclaration(node))) return;
8505
8999
  if (isHookUsage(node, hook)) {
8506
9000
  let current = node;
8507
9001
  let isInJsxChild = false;
8508
- while (!ts13.isSourceFile(current)) {
9002
+ while (!ts14.isSourceFile(current)) {
8509
9003
  if (children.includes(current)) {
8510
9004
  isInJsxChild = true;
8511
9005
  break;
@@ -8514,14 +9008,14 @@ function usesOutsideJsx(declaration, hook, children) {
8514
9008
  }
8515
9009
  if (!isInJsxChild) outside = true;
8516
9010
  }
8517
- ts13.forEachChild(node, visit);
9011
+ ts14.forEachChild(node, visit);
8518
9012
  };
8519
9013
  visit(declaration);
8520
9014
  return outside;
8521
9015
  }
8522
9016
 
8523
9017
  // eslint/rules/source-under-src.ts
8524
- import path56 from "path";
9018
+ import path59 from "path";
8525
9019
  var NON_SOURCE_ROOT_DIRS = /* @__PURE__ */ new Set([
8526
9020
  ".agents",
8527
9021
  ".cache",
@@ -8562,14 +9056,14 @@ var sourceUnderSrcRule = {
8562
9056
  }
8563
9057
  },
8564
9058
  create(context) {
8565
- const filename = path56.resolve(context.filename);
9059
+ const filename = path59.resolve(context.filename);
8566
9060
  if (!MODULE_EXTENSION.test(filename)) return {};
8567
- const relative = path56.relative(context.cwd, filename).replace(/\\/g, "/");
9061
+ const relative = path59.relative(context.cwd, filename).replace(/\\/g, "/");
8568
9062
  if (relative === "src" || relative.startsWith("src/")) return {};
8569
9063
  const topLevel = relative.split("/")[0] ?? "";
8570
9064
  if (NON_SOURCE_ROOT_DIRS.has(topLevel)) return {};
8571
9065
  if (!relative.includes("/")) {
8572
- const basename = path56.basename(filename);
9066
+ const basename = path59.basename(filename);
8573
9067
  if (CONFIG_FILE.test(basename) || DECLARATION_FILE.test(basename) || basename.startsWith(".")) return {};
8574
9068
  }
8575
9069
  return {
@@ -8585,7 +9079,7 @@ var sourceUnderSrcRule = {
8585
9079
  };
8586
9080
 
8587
9081
  // eslint/rules/stay-flat.ts
8588
- import path57 from "path";
9082
+ import path60 from "path";
8589
9083
  var stayFlatRule = {
8590
9084
  meta: {
8591
9085
  schema: [],
@@ -8596,7 +9090,7 @@ var stayFlatRule = {
8596
9090
  },
8597
9091
  create(context) {
8598
9092
  const sourceRoot = sourceRootOf(context);
8599
- const file = path57.resolve(context.filename);
9093
+ const file = path60.resolve(context.filename);
8600
9094
  const segments = segmentsOf(file, sourceRoot);
8601
9095
  if (segments.length !== 3 || segments[0] !== "features") return {};
8602
9096
  const index = getProjectIndex(sourceRoot);
@@ -8636,7 +9130,7 @@ var stayFlatRule = {
8636
9130
  };
8637
9131
 
8638
9132
  // eslint/rules/support-file-placement.ts
8639
- import path58 from "path";
9133
+ import path61 from "path";
8640
9134
  var CONFIG_OWNED_FOLDERS = /* @__PURE__ */ new Set(["types", "constants"]);
8641
9135
  var EXPORT_KIND_BY_SUPPORT_FOLDER = /* @__PURE__ */ new Map([
8642
9136
  ["constants", "constant"],
@@ -8661,7 +9155,7 @@ var supportFilePlacementRule = {
8661
9155
  },
8662
9156
  create(context) {
8663
9157
  const sourceRoot = sourceRootOf(context);
8664
- const supportFile = path58.resolve(context.filename);
9158
+ const supportFile = path61.resolve(context.filename);
8665
9159
  const currentFolder = folderSegmentsOf(supportFile, sourceRoot);
8666
9160
  const supportFolder = currentFolder[currentFolder.length - 1];
8667
9161
  if (supportFolder === void 0 || !SUPPORT_FOLDERS.has(supportFolder)) return {};
@@ -8715,7 +9209,7 @@ var supportFilePlacementRule = {
8715
9209
 
8716
9210
  // eslint/rules/support-folder-shape.ts
8717
9211
  import fs6 from "fs";
8718
- import path59 from "path";
9212
+ import path62 from "path";
8719
9213
  var SUPPORT_FOLDERS4 = /* @__PURE__ */ new Set(["constants", "types", "schemas"]);
8720
9214
  var INDEX_NAMES2 = /* @__PURE__ */ new Set(["index.ts", "index.tsx", "index.mts", "index.cts"]);
8721
9215
  var supportFolderShapeRule = {
@@ -8727,12 +9221,12 @@ var supportFolderShapeRule = {
8727
9221
  }
8728
9222
  },
8729
9223
  create(context) {
8730
- const filename = path59.resolve(context.filename);
8731
- const baseName = path59.basename(filename);
9224
+ const filename = path62.resolve(context.filename);
9225
+ const baseName = path62.basename(filename);
8732
9226
  if (!INDEX_NAMES2.has(baseName)) return {};
8733
- const folder = path59.basename(path59.dirname(filename));
9227
+ const folder = path62.basename(path62.dirname(filename));
8734
9228
  if (!SUPPORT_FOLDERS4.has(folder)) return {};
8735
- const directory = path59.dirname(filename);
9229
+ const directory = path62.dirname(filename);
8736
9230
  let entries;
8737
9231
  try {
8738
9232
  entries = fs6.readdirSync(directory);
@@ -8750,7 +9244,7 @@ var supportFolderShapeRule = {
8750
9244
  for (const match of source.matchAll(exportPattern)) {
8751
9245
  hasAnyReExport = true;
8752
9246
  const specifier = match.groups?.specifier;
8753
- if (specifier?.startsWith(".")) exportedFiles.add(path59.basename(specifier));
9247
+ if (specifier?.startsWith(".")) exportedFiles.add(path62.basename(specifier));
8754
9248
  }
8755
9249
  const guide = `docs/next-codebase-guide/rules/${folder === "constants" ? "constants" : "types-and-schemas"}-rule.md`;
8756
9250
  if (siblingModules.length === 0) {
@@ -8929,24 +9423,24 @@ var baseLayerPairRule = {
8929
9423
 
8930
9424
  // eslint/rules/tailwind/css-entry-point.ts
8931
9425
  import { statSync as statSync4 } from "fs";
8932
- import path62 from "path";
9426
+ import path65 from "path";
8933
9427
 
8934
9428
  // eslint/rules/tailwind/source-files.ts
8935
- import { readdirSync as readdirSync3, readFileSync as readFileSync11, statSync as statSync3 } from "fs";
8936
- import path60 from "path";
9429
+ import { readdirSync as readdirSync5, readFileSync as readFileSync13, statSync as statSync3 } from "fs";
9430
+ import path63 from "path";
8937
9431
  var CSS_EXTENSIONS = [".css"];
8938
9432
  var MODULE_EXTENSIONS4 = [".ts", ".tsx", ".mts", ".cts", ".js", ".jsx", ".mjs", ".cjs"];
8939
9433
  var SOURCE_EXTENSIONS = [...MODULE_EXTENSIONS4, ...CSS_EXTENSIONS];
8940
9434
  function findFiles(dir, extensions) {
8941
9435
  let entries;
8942
9436
  try {
8943
- entries = readdirSync3(dir);
9437
+ entries = readdirSync5(dir);
8944
9438
  } catch {
8945
9439
  return [];
8946
9440
  }
8947
9441
  return entries.flatMap((entry) => {
8948
9442
  if (entry.startsWith(".") || entry === "node_modules") return [];
8949
- const entryPath = path60.join(dir, entry);
9443
+ const entryPath = path63.join(dir, entry);
8950
9444
  let stats;
8951
9445
  try {
8952
9446
  stats = statSync3(entryPath);
@@ -8954,7 +9448,7 @@ function findFiles(dir, extensions) {
8954
9448
  return [];
8955
9449
  }
8956
9450
  if (stats.isDirectory()) return findFiles(entryPath, extensions);
8957
- return extensions.includes(path60.extname(entry)) ? [entryPath] : [];
9451
+ return extensions.includes(path63.extname(entry)) ? [entryPath] : [];
8958
9452
  });
8959
9453
  }
8960
9454
  function cachedTextReader() {
@@ -8963,7 +9457,7 @@ function cachedTextReader() {
8963
9457
  let text = texts.get(file);
8964
9458
  if (text === void 0) {
8965
9459
  try {
8966
- text = readFileSync11(file, "utf8");
9460
+ text = readFileSync13(file, "utf8");
8967
9461
  } catch {
8968
9462
  text = "";
8969
9463
  }
@@ -8977,7 +9471,7 @@ function escapeRegExp(text) {
8977
9471
  }
8978
9472
 
8979
9473
  // eslint/rules/tailwind/stylesheet-graph.ts
8980
- import path61 from "path";
9474
+ import path64 from "path";
8981
9475
  function registersTailwind(text) {
8982
9476
  return /@import\s+(?:url\(\s*)?["']tailwindcss["']\s*\)?/i.test(text);
8983
9477
  }
@@ -8991,25 +9485,25 @@ function moduleImports(text, fileName) {
8991
9485
  return new RegExp(`(?:import|require)\\s*\\(?\\s*["'][^"']*${escaped}["']`, "i").test(text);
8992
9486
  }
8993
9487
  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));
9488
+ if (spec.startsWith("/")) return path64.resolve(spec);
9489
+ if (spec.startsWith("./") || spec.startsWith("../")) return path64.resolve(path64.dirname(fromFile), spec);
9490
+ if (spec.startsWith("@/")) return path64.resolve(sourceRoot, spec.slice(2));
8997
9491
  return void 0;
8998
9492
  }
8999
9493
  function buildStylesheetGraph(options) {
9000
9494
  const { cssFiles, sourceRoot, textOf } = options;
9001
- const cssSet = new Set(cssFiles.map((file) => path61.normalize(file)));
9495
+ const cssSet = new Set(cssFiles.map((file) => path64.normalize(file)));
9002
9496
  const globals = cssFiles.filter((file) => registersTailwind(textOf(file)));
9003
9497
  const reachable = /* @__PURE__ */ new Set();
9004
9498
  const queue = [...globals];
9005
- for (const global of globals) reachable.add(path61.normalize(global));
9499
+ for (const global of globals) reachable.add(path64.normalize(global));
9006
9500
  while (queue.length > 0) {
9007
9501
  const from = queue.shift();
9008
9502
  if (!from) continue;
9009
9503
  for (const spec of importedSpecifiers(textOf(from))) {
9010
9504
  const target = resolveSpecifier2(from, spec, sourceRoot);
9011
9505
  if (!target) continue;
9012
- const normalized = path61.normalize(target);
9506
+ const normalized = path64.normalize(target);
9013
9507
  if (cssSet.has(normalized) && !reachable.has(normalized)) {
9014
9508
  reachable.add(normalized);
9015
9509
  queue.push(normalized);
@@ -9021,7 +9515,7 @@ function buildStylesheetGraph(options) {
9021
9515
  for (const spec of importedSpecifiers(textOf(global))) {
9022
9516
  const target = resolveSpecifier2(global, spec, sourceRoot);
9023
9517
  if (!target) continue;
9024
- const normalized = path61.normalize(target);
9518
+ const normalized = path64.normalize(target);
9025
9519
  if (cssSet.has(normalized)) directChildren.add(normalized);
9026
9520
  }
9027
9521
  }
@@ -9029,8 +9523,8 @@ function buildStylesheetGraph(options) {
9029
9523
  }
9030
9524
 
9031
9525
  // 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");
9526
+ var APP_STYLES_DIR = path65.join("app", "styles");
9527
+ var GLOBAL_STYLESHEET_PATH = path65.join(APP_STYLES_DIR, "globals.css");
9034
9528
  var cssEntryPointRule = {
9035
9529
  meta: {
9036
9530
  schema: [],
@@ -9056,8 +9550,8 @@ var cssEntryPointRule = {
9056
9550
  return {
9057
9551
  "StyleSheet:exit"(node) {
9058
9552
  if (globals.length === 0) return;
9059
- const current = path62.normalize(path62.resolve(context.filename));
9060
- const relative = path62.relative(sourceRoot, current);
9553
+ const current = path65.normalize(path65.resolve(context.filename));
9554
+ const relative = path65.relative(sourceRoot, current);
9061
9555
  if (globals.includes(current)) {
9062
9556
  if (globals.length > 1) {
9063
9557
  context.report({
@@ -9073,7 +9567,7 @@ var cssEntryPointRule = {
9073
9567
  });
9074
9568
  return;
9075
9569
  }
9076
- const basename = path62.basename(current);
9570
+ const basename = path65.basename(current);
9077
9571
  const importCount = moduleFiles.filter((modulePath) => moduleImports(textOf(modulePath), basename)).length;
9078
9572
  if (importCount !== 1) {
9079
9573
  context.report({
@@ -9083,7 +9577,7 @@ var cssEntryPointRule = {
9083
9577
  }
9084
9578
  return;
9085
9579
  }
9086
- const isInAppStyles = relative === APP_STYLES_DIR || relative.startsWith(`${APP_STYLES_DIR}${path62.sep}`);
9580
+ const isInAppStyles = relative === APP_STYLES_DIR || relative.startsWith(`${APP_STYLES_DIR}${path65.sep}`);
9087
9581
  if (!isInAppStyles) {
9088
9582
  context.report({
9089
9583
  node,
@@ -9572,7 +10066,7 @@ var tailwindRules = {
9572
10066
  };
9573
10067
 
9574
10068
  // eslint/rules/type-extraction.ts
9575
- import path63 from "path";
10069
+ import path66 from "path";
9576
10070
  var typeExtractionRule = {
9577
10071
  meta: {
9578
10072
  schema: [],
@@ -9583,7 +10077,7 @@ var typeExtractionRule = {
9583
10077
  },
9584
10078
  create(context) {
9585
10079
  const sourceRoot = sourceRootOf(context);
9586
- const file = path63.resolve(context.filename);
10080
+ const file = path66.resolve(context.filename);
9587
10081
  const segments = segmentsOf(file, sourceRoot);
9588
10082
  if (segments.length === 0) return {};
9589
10083
  const index = getProjectIndex(sourceRoot);
@@ -9722,9 +10216,9 @@ var uiStateRule = {
9722
10216
  };
9723
10217
 
9724
10218
  // eslint/rules/unknown-utility.ts
9725
- import { existsSync as existsSync6, readdirSync as readdirSync4, readFileSync as readFileSync12, statSync as statSync6 } from "fs";
10219
+ import { existsSync as existsSync8, readdirSync as readdirSync6, readFileSync as readFileSync14, statSync as statSync6 } from "fs";
9726
10220
  import { createRequire } from "module";
9727
- import path64 from "path";
10221
+ import path67 from "path";
9728
10222
  var PREFIX_NAMESPACES = {
9729
10223
  bg: ["color"],
9730
10224
  text: ["color", "text"],
@@ -9958,13 +10452,13 @@ function isBuiltInTailwindUtility(utility) {
9958
10452
  function stylesheetFiles(dir) {
9959
10453
  let entries;
9960
10454
  try {
9961
- entries = readdirSync4(dir);
10455
+ entries = readdirSync6(dir);
9962
10456
  } catch {
9963
10457
  return [];
9964
10458
  }
9965
10459
  return entries.flatMap((entry) => {
9966
10460
  if (entry.startsWith(".") || entry === "node_modules") return [];
9967
- const entryPath = path64.join(dir, entry);
10461
+ const entryPath = path67.join(dir, entry);
9968
10462
  let stats;
9969
10463
  try {
9970
10464
  stats = statSync6(entryPath);
@@ -9972,7 +10466,7 @@ function stylesheetFiles(dir) {
9972
10466
  return [];
9973
10467
  }
9974
10468
  if (stats.isDirectory()) return stylesheetFiles(entryPath);
9975
- return path64.extname(entry) === ".css" ? [entryPath] : [];
10469
+ return path67.extname(entry) === ".css" ? [entryPath] : [];
9976
10470
  });
9977
10471
  }
9978
10472
  function packageNameOf(specifier) {
@@ -9983,24 +10477,24 @@ function packageNameOf(specifier) {
9983
10477
  function resolvePackageStylesheet(fromFile, specifier) {
9984
10478
  const packageName = packageNameOf(specifier);
9985
10479
  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)) {
10480
+ let directory = path67.dirname(fromFile);
10481
+ while (directory !== path67.dirname(directory)) {
10482
+ const packageRoot = path67.join(directory, "node_modules", packageName);
10483
+ const manifestPath = path67.join(packageRoot, "package.json");
10484
+ if (existsSync8(manifestPath)) {
9991
10485
  try {
9992
- const manifest = readFileSync12(manifestPath, "utf8");
10486
+ const manifest = readFileSync14(manifestPath, "utf8");
9993
10487
  const stylesheet = /"style"\s*:\s*"(?<file>[^"]+\.css)"/.exec(manifest)?.groups?.file;
9994
10488
  const main = /"main"\s*:\s*"(?<file>[^"]+\.css)"/.exec(manifest)?.groups?.file;
9995
10489
  const target = stylesheet ?? main;
9996
10490
  if (!target) return void 0;
9997
- const resolved = path64.resolve(packageRoot, target);
9998
- return existsSync6(resolved) ? resolved : void 0;
10491
+ const resolved = path67.resolve(packageRoot, target);
10492
+ return existsSync8(resolved) ? resolved : void 0;
9999
10493
  } catch {
10000
10494
  return void 0;
10001
10495
  }
10002
10496
  }
10003
- directory = path64.dirname(directory);
10497
+ directory = path67.dirname(directory);
10004
10498
  }
10005
10499
  return void 0;
10006
10500
  }
@@ -10009,7 +10503,7 @@ function inventoryStylesheetFiles(projectFiles) {
10009
10503
  for (const file of projectFiles) {
10010
10504
  let css2;
10011
10505
  try {
10012
- css2 = readFileSync12(file, "utf8");
10506
+ css2 = readFileSync14(file, "utf8");
10013
10507
  } catch {
10014
10508
  continue;
10015
10509
  }
@@ -10075,7 +10569,7 @@ function readInventory(files) {
10075
10569
  for (const file of files) {
10076
10570
  let css2;
10077
10571
  try {
10078
- css2 = readFileSync12(file, "utf8");
10572
+ css2 = readFileSync14(file, "utf8");
10079
10573
  } catch {
10080
10574
  continue;
10081
10575
  }
@@ -10251,7 +10745,7 @@ var unknownUtilityRule = {
10251
10745
  };
10252
10746
 
10253
10747
  // eslint/rules/util-file-name.ts
10254
- import path65 from "path";
10748
+ import path68 from "path";
10255
10749
  function toKebabCase2(value) {
10256
10750
  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
10751
  }
@@ -10264,7 +10758,7 @@ var utilFileNameRule = {
10264
10758
  }
10265
10759
  },
10266
10760
  create(context) {
10267
- const filename = path65.resolve(context.filename);
10761
+ const filename = path68.resolve(context.filename);
10268
10762
  const segments = filename.replace(/\\/g, "/").split("/");
10269
10763
  if (!segments.includes("utils")) return {};
10270
10764
  let module;
@@ -10278,13 +10772,13 @@ var utilFileNameRule = {
10278
10772
  const functionName = functions[0]?.name;
10279
10773
  if (!functionName) return {};
10280
10774
  const expected = toKebabCase2(functionName);
10281
- const actual = path65.basename(filename, path65.extname(filename));
10775
+ const actual = path68.basename(filename, path68.extname(filename));
10282
10776
  if (!expected || actual === expected) return {};
10283
10777
  return {
10284
10778
  Program(node) {
10285
10779
  context.report({
10286
10780
  node,
10287
- message: `A utility file exporting ${functionName} must be named ${expected}.${path65.extname(filename).slice(1)}.`
10781
+ message: `A utility file exporting ${functionName} must be named ${expected}.${path68.extname(filename).slice(1)}.`
10288
10782
  });
10289
10783
  }
10290
10784
  };
@@ -10292,7 +10786,7 @@ var utilFileNameRule = {
10292
10786
  };
10293
10787
 
10294
10788
  // eslint/rules/value-extraction.ts
10295
- import path66 from "path";
10789
+ import path69 from "path";
10296
10790
  var valueExtractionRule = {
10297
10791
  meta: {
10298
10792
  schema: [],
@@ -10303,7 +10797,7 @@ var valueExtractionRule = {
10303
10797
  },
10304
10798
  create(context) {
10305
10799
  const sourceRoot = sourceRootOf(context);
10306
- const file = path66.resolve(context.filename);
10800
+ const file = path69.resolve(context.filename);
10307
10801
  const segments = segmentsOf(file, sourceRoot);
10308
10802
  if (segments.length === 0 || segments[0] !== "app") return {};
10309
10803
  const index = getProjectIndex(sourceRoot);
@@ -10324,8 +10818,8 @@ var valueExtractionRule = {
10324
10818
  };
10325
10819
 
10326
10820
  // eslint/rules/vulyk/tracked-docs.ts
10327
- import { existsSync as existsSync7, readFileSync as readFileSync13 } from "fs";
10328
- import path67 from "path";
10821
+ import { existsSync as existsSync9, readFileSync as readFileSync15 } from "fs";
10822
+ import path70 from "path";
10329
10823
  var PASIKA_REPO = "Bredansky/pasika";
10330
10824
  var BASE_REQUIRED_TRACKED_DOCS = [
10331
10825
  { name: "documentation-guide", path: "docs/documentation-guide" },
@@ -10336,13 +10830,13 @@ var NEXTJS_REQUIRED_TRACKED_DOCS = [
10336
10830
  { name: "next-codebase-guide", path: "docs/next-codebase-guide" },
10337
10831
  { name: "next-tailwind-guide", path: "docs/next-tailwind-guide" }
10338
10832
  ];
10339
- function memberName7(member) {
10833
+ function memberName8(member) {
10340
10834
  return member.name.type === "String" ? member.name.value : member.name.name;
10341
10835
  }
10342
10836
  function hasDependency(root, name) {
10343
- const section = root.members.find((member) => memberName7(member) === "dependencies");
10837
+ const section = root.members.find((member) => memberName8(member) === "dependencies");
10344
10838
  if (section?.value.type !== "Object") return false;
10345
- return section.value.members.some((member) => memberName7(member) === name);
10839
+ return section.value.members.some((member) => memberName8(member) === name);
10346
10840
  }
10347
10841
  var trackedDocsRule = {
10348
10842
  meta: {
@@ -10358,16 +10852,16 @@ var trackedDocsRule = {
10358
10852
  if (!context.filename.endsWith("package.json")) return;
10359
10853
  const root = node.body;
10360
10854
  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)) {
10855
+ const projectRoot = path70.dirname(path70.resolve(context.filename));
10856
+ const configPath = path70.join(projectRoot, "vulyk.config.ts");
10857
+ if (!existsSync9(configPath)) {
10364
10858
  context.report({
10365
10859
  node,
10366
10860
  message: "No vulyk.config.ts found. Run npx vulyk init to create one that tracks the framework's required tracked docs."
10367
10861
  });
10368
10862
  return;
10369
10863
  }
10370
- const config = readFileSync13(configPath, "utf8");
10864
+ const config = readFileSync15(configPath, "utf8");
10371
10865
  if (!config.includes(PASIKA_REPO)) {
10372
10866
  context.report({
10373
10867
  node,
@@ -10384,8 +10878,8 @@ var trackedDocsRule = {
10384
10878
  });
10385
10879
  }
10386
10880
  }
10387
- const agentsPath = path67.join(projectRoot, "AGENTS.md");
10388
- if (!existsSync7(agentsPath)) {
10881
+ const agentsPath = path70.join(projectRoot, "AGENTS.md");
10882
+ if (!existsSync9(agentsPath)) {
10389
10883
  context.report({
10390
10884
  node,
10391
10885
  message: "No AGENTS.md found. Run npx vulyk agents to generate the agent file that routes to the tracked docs."
@@ -10397,14 +10891,14 @@ var trackedDocsRule = {
10397
10891
  };
10398
10892
 
10399
10893
  // eslint/rules/vulyk/vulyk-dependency.ts
10400
- function memberName8(member) {
10894
+ function memberName9(member) {
10401
10895
  return member.name.type === "String" ? member.name.value : member.name.name;
10402
10896
  }
10403
10897
  function dependency(root, sectionName) {
10404
10898
  if (root.type !== "Object") return void 0;
10405
- const section = root.members.find((member) => memberName8(member) === sectionName);
10899
+ const section = root.members.find((member) => memberName9(member) === sectionName);
10406
10900
  if (section?.value.type !== "Object") return void 0;
10407
- return section.value.members.find((member) => memberName8(member) === "vulyk");
10901
+ return section.value.members.find((member) => memberName9(member) === "vulyk");
10408
10902
  }
10409
10903
  var vulykDependencyRule = {
10410
10904
  meta: {
@@ -10445,9 +10939,9 @@ var vulykRules = {
10445
10939
  // eslint/rules/with-response-helper.ts
10446
10940
  var HELPER3 = "withResponse";
10447
10941
  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}`;
10942
+ var DOC9 = "docs/pasika-adoption-guide/rules/with-response-helper-rule.md";
10943
+ var DECLARED3 = `A repository must not declare its own ${HELPER3}; import it from ${ENTRY3}. See ${DOC9}`;
10944
+ var IMPORTED3 = `${HELPER3} must be imported from ${ENTRY3}. See ${DOC9}`;
10451
10945
  function isNamed3(node, name) {
10452
10946
  return node?.type === "Identifier" && node.name === name;
10453
10947
  }
@@ -10484,7 +10978,7 @@ var withResponseHelperRule = {
10484
10978
 
10485
10979
  // eslint/rules/zirka-baseline.ts
10486
10980
  import fs7 from "fs";
10487
- import path68 from "path";
10981
+ import path71 from "path";
10488
10982
  var ESLINT_CONFIG = /^eslint\.config\.(?:ts|mts|cts|js|mjs|cjs)$/;
10489
10983
  var PRETTIER_CONFIGS = [
10490
10984
  "prettier.config.mjs",
@@ -10503,10 +10997,10 @@ var zirkaBaselineRule = {
10503
10997
  }
10504
10998
  },
10505
10999
  create(context) {
10506
- const filename = path68.resolve(context.filename);
10507
- const basename = path68.basename(filename);
11000
+ const filename = path71.resolve(context.filename);
11001
+ const basename = path71.basename(filename);
10508
11002
  if (!ESLINT_CONFIG.test(basename)) return {};
10509
- const projectRoot = path68.dirname(filename);
11003
+ const projectRoot = path71.dirname(filename);
10510
11004
  const report3 = (message) => {
10511
11005
  context.report({
10512
11006
  node: context.sourceCode.ast,
@@ -10521,7 +11015,7 @@ var zirkaBaselineRule = {
10521
11015
  'ESLint config must take its configuration from zirka (import { styleguide } from "zirka") instead of restating rules locally.'
10522
11016
  );
10523
11017
  }
10524
- const tsconfigPath = path68.join(projectRoot, "tsconfig.json");
11018
+ const tsconfigPath = path71.join(projectRoot, "tsconfig.json");
10525
11019
  if (!fs7.existsSync(tsconfigPath)) {
10526
11020
  report3('No tsconfig.json found. Create one extending the zirka TypeScript base config ("zirka/typescript").');
10527
11021
  } else {
@@ -10539,13 +11033,13 @@ var zirkaBaselineRule = {
10539
11033
  report3('tsconfig.json must extend the zirka TypeScript base config ("zirka/typescript").');
10540
11034
  }
10541
11035
  }
10542
- const prettierConfigFile = PRETTIER_CONFIGS.find((name) => fs7.existsSync(path68.join(projectRoot, name)));
11036
+ const prettierConfigFile = PRETTIER_CONFIGS.find((name) => fs7.existsSync(path71.join(projectRoot, name)));
10543
11037
  if (!prettierConfigFile) {
10544
11038
  report3(
10545
11039
  "No prettier config found. Create one that takes its configuration from zirka (styleguide({ prettier: true }).prettierConfig)."
10546
11040
  );
10547
11041
  } else {
10548
- const content = fs7.readFileSync(path68.join(projectRoot, prettierConfigFile), "utf8");
11042
+ const content = fs7.readFileSync(path71.join(projectRoot, prettierConfigFile), "utf8");
10549
11043
  if (!content.includes("zirka")) {
10550
11044
  report3(
10551
11045
  "The prettier config must take its configuration from zirka (styleguide({ prettier: true }).prettierConfig) instead of restating it locally."
@@ -10568,10 +11062,10 @@ function referencesZirka(sourceCode) {
10568
11062
  // eslint/rules/zod-fetch-helper.ts
10569
11063
  var HELPER4 = "zodFetch";
10570
11064
  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}`;
11065
+ var DOC10 = "docs/pasika-adoption-guide/rules/zod-fetch-helper-rule.md";
11066
+ var FETCHED = `fetch must not be called; make the request through ${HELPER4} from ${ENTRY4}. See ${DOC10}`;
11067
+ var DECLARED4 = `A file must not declare its own ${HELPER4}; import it from ${ENTRY4}. See ${DOC10}`;
11068
+ var IMPORTED4 = `${HELPER4} must be imported from ${ENTRY4}. See ${DOC10}`;
10575
11069
  var GLOBAL_OBJECTS = /* @__PURE__ */ new Set(["globalThis", "window", "self", "global"]);
10576
11070
  var TEST_FILE2 = /(?:^|[\\/])(?:__tests__|tests)[\\/]|[.](?:test|spec)[.][cm]?[jt]sx?$/;
10577
11071
  function isNamed4(node, name) {
@@ -10691,14 +11185,14 @@ var zodSchemaValidationRule = {
10691
11185
  };
10692
11186
 
10693
11187
  // eslint/ts-alignment.ts
10694
- import { readFileSync as readFileSync14 } from "fs";
11188
+ import { readFileSync as readFileSync16 } from "fs";
10695
11189
  import { createRequire as createRequire2 } from "module";
10696
11190
  import { join } from "path";
10697
11191
  var ownRequire = createRequire2(import.meta.url);
10698
11192
  var majorOf = (version) => Number(version.split(".")[0]);
10699
11193
  function versionOf(packagePath) {
10700
11194
  try {
10701
- const parsed = JSON.parse(readFileSync14(packagePath, "utf8"));
11195
+ const parsed = JSON.parse(readFileSync16(packagePath, "utf8"));
10702
11196
  if (typeof parsed !== "object" || parsed === null || !("version" in parsed)) return null;
10703
11197
  return typeof parsed.version === "string" ? parsed.version : null;
10704
11198
  } catch {