pasika 0.10.100 → 0.10.102

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -38,8 +38,8 @@ function memberPropertyName(node) {
38
38
  }
39
39
  return void 0;
40
40
  }
41
- function importedContractMember(expression, propertyName5, imports) {
42
- if (expression?.type !== "MemberExpression" || memberPropertyName(expression) !== propertyName5 || expression.object.type !== "Identifier" || !imports.has(expression.object.name)) {
41
+ function importedContractMember(expression, propertyName6, imports) {
42
+ if (expression?.type !== "MemberExpression" || memberPropertyName(expression) !== propertyName6 || expression.object.type !== "Identifier" || !imports.has(expression.object.name)) {
43
43
  return void 0;
44
44
  }
45
45
  return expression.object.name;
@@ -1878,8 +1878,8 @@ function collectSections(node) {
1878
1878
  function collectSteps(content, section) {
1879
1879
  const lists = content.filter((node) => node.type === "list");
1880
1880
  const paragraphs = content.filter((node) => node.type === "paragraph");
1881
- const steps = lists.length > 0 ? lists.flatMap((list) => list.children) : paragraphs.slice(content[0]?.type === "paragraph" ? 1 : 0);
1882
- for (const step of steps) {
1881
+ const steps2 = lists.length > 0 ? lists.flatMap((list) => list.children) : paragraphs.slice(content[0]?.type === "paragraph" ? 1 : 0);
1882
+ for (const step of steps2) {
1883
1883
  section.stepTexts.push(getTextContent(step));
1884
1884
  if (section.stepTexts.length === 1) collectDocLinks(step, section.firstStepLinks);
1885
1885
  }
@@ -2316,11 +2316,11 @@ var guideStepSingleSentenceRule = {
2316
2316
  if (!filename.endsWith("-guide.md")) return;
2317
2317
  if (!listsOnPath.at(-1)?.ordered) return;
2318
2318
  const text = getTextContent(node).trim();
2319
- const sentenceCount = countSentences(text);
2320
- if (sentenceCount > 1) {
2319
+ const sentenceCount2 = countSentences(text);
2320
+ if (sentenceCount2 > 1) {
2321
2321
  context.report({
2322
2322
  node,
2323
- message: `step uses ${String(sentenceCount)} sentences`
2323
+ message: `step uses ${String(sentenceCount2)} sentences`
2324
2324
  });
2325
2325
  }
2326
2326
  }
@@ -2453,7 +2453,7 @@ var overviewRule = {
2453
2453
  }
2454
2454
  }
2455
2455
  if (!titleLine) return;
2456
- let sentenceCount = 0;
2456
+ let sentenceCount2 = 0;
2457
2457
  let found = false;
2458
2458
  for (const child of node.children) {
2459
2459
  if (child.type === "heading" && getLine(child) > titleLine) break;
@@ -2467,11 +2467,11 @@ var overviewRule = {
2467
2467
  message: "overview links another document"
2468
2468
  });
2469
2469
  }
2470
- sentenceCount += countSentences2(text);
2471
- if (sentenceCount > 2) {
2470
+ sentenceCount2 += countSentences2(text);
2471
+ if (sentenceCount2 > 2) {
2472
2472
  context.report({
2473
2473
  node: child,
2474
- message: `overview uses ${String(sentenceCount)} sentences, at most two are allowed`
2474
+ message: `overview uses ${String(sentenceCount2)} sentences, at most two are allowed`
2475
2475
  });
2476
2476
  break;
2477
2477
  }
@@ -2822,6 +2822,43 @@ var rulePairedExamplesRule = {
2822
2822
  message: `Rule level-2 heading must be an Incorrect/Correct example: ${text}`
2823
2823
  });
2824
2824
  }
2825
+ const firstExampleIndex = node.children.findIndex((child) => child.type === "heading" && child.depth === 2);
2826
+ const requirementsIndex = node.children.findIndex(
2827
+ (child, index) => index < firstExampleIndex && child.type === "list" && !child.ordered
2828
+ );
2829
+ if (requirementsIndex !== -1) {
2830
+ const requirements = node.children[requirementsIndex];
2831
+ if (requirements?.type === "list" && requirements.spread) {
2832
+ context.report({
2833
+ node: requirements,
2834
+ message: "Rule requirement bullets must form one uninterrupted list without blank lines"
2835
+ });
2836
+ }
2837
+ for (const child of node.children.slice(requirementsIndex + 1, firstExampleIndex)) {
2838
+ context.report({
2839
+ node: child,
2840
+ message: "Rule requirements must be followed directly by the first Incorrect/Correct example"
2841
+ });
2842
+ }
2843
+ }
2844
+ let inExample = false;
2845
+ let afterWhy = false;
2846
+ for (const child of node.children) {
2847
+ if (child.type === "heading" && child.depth === 2) {
2848
+ inExample = true;
2849
+ afterWhy = false;
2850
+ continue;
2851
+ }
2852
+ if (!inExample) continue;
2853
+ if (afterWhy) {
2854
+ context.report({
2855
+ node: child,
2856
+ message: "A Why explanation must be the final block of its example"
2857
+ });
2858
+ } else if (child.type === "paragraph" && getTextContent(child).trim().startsWith("Why:")) {
2859
+ afterWhy = true;
2860
+ }
2861
+ }
2825
2862
  const incorrect = exampleHeadings.filter((h) => h.text.startsWith("Incorrect"));
2826
2863
  const correct = exampleHeadings.filter((h) => h.text.startsWith("Correct"));
2827
2864
  if (incorrect.length === 0 || incorrect.length !== correct.length) {
@@ -2922,6 +2959,38 @@ var titleMatchesFileNameRule = {
2922
2959
  }
2923
2960
  };
2924
2961
 
2962
+ // eslint/rules/documentation/why-sentence-limit.ts
2963
+ var MAX_SENTENCES = 2;
2964
+ function sentenceCount(text) {
2965
+ const normalized = text.replace(/\b(?:e\.g|i\.e)\./gi, (match) => match.replaceAll(".", ""));
2966
+ return normalized.split(/[.!?]+["'’”\])]*(?:\s+|$)/).filter((part) => part.trim().length > 0).length;
2967
+ }
2968
+ var whySentenceLimitRule = {
2969
+ meta: {
2970
+ type: "problem",
2971
+ docs: {
2972
+ description: "Why explanations in Rules may use at most two sentences.",
2973
+ recommended: true
2974
+ }
2975
+ },
2976
+ create(context) {
2977
+ return {
2978
+ paragraph(node) {
2979
+ if (!getFilename(context).endsWith("-rule.md")) return;
2980
+ const text = node.children.map((child) => child.type === "inlineCode" ? "code" : getTextContent(child)).join("").trim();
2981
+ if (!text.startsWith("Why:")) return;
2982
+ const count = sentenceCount(text.slice("Why:".length).trim());
2983
+ if (count > MAX_SENTENCES) {
2984
+ context.report({
2985
+ node,
2986
+ message: `Why explanation has ${String(count)} sentences; maximum is ${String(MAX_SENTENCES)}.`
2987
+ });
2988
+ }
2989
+ }
2990
+ };
2991
+ }
2992
+ };
2993
+
2925
2994
  // eslint/rules/documentation/index.ts
2926
2995
  var documentationRules = {
2927
2996
  "doc-kind-suffix": docKindSuffixRule,
@@ -2932,6 +3001,7 @@ var documentationRules = {
2932
3001
  "guide-states-no-requirement": guideStatesNoRequirementRule,
2933
3002
  "requirement-present": requirementPresentRule,
2934
3003
  "rule-paired-examples": rulePairedExamplesRule,
3004
+ "why-sentence-limit": whySentenceLimitRule,
2935
3005
  "example-heading-description": exampleHeadingDescriptionRule,
2936
3006
  "policy-no-examples": policyNoExamplesRule,
2937
3007
  "no-cross-document-link": noCrossDocumentLinkRule,
@@ -3832,6 +3902,7 @@ var huskyHookRule = {
3832
3902
  return;
3833
3903
  }
3834
3904
  const content = readFileSync6(hookPath, "utf8");
3905
+ const commands = content.replace(/^[ \t]*#[^\r\n]*$/gm, "");
3835
3906
  const scripts = root.members.find((member) => memberName(member) === "scripts");
3836
3907
  const scriptNames = new Set(scripts?.value.type === "Object" ? scripts.value.members.map(memberName) : []);
3837
3908
  const requireNamedScript = (name) => {
@@ -3847,6 +3918,37 @@ var huskyHookRule = {
3847
3918
  }
3848
3919
  requireNamedScript("typecheck");
3849
3920
  requireNamedScript("test:unit:coverage");
3921
+ const autoStageAll = /^\s*git\s+add\s+(?:--\s+)?(?:-A|--all|-u|\.)(?:\s*(?:#.*)?)?$/m.test(commands);
3922
+ const coverageIndex = commands.indexOf("npm run test:unit:coverage");
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) {
3926
+ context.report({
3927
+ node,
3928
+ message: ".husky/pre-commit must reject unstaged vitest.config.ts changes after coverage."
3929
+ });
3930
+ }
3931
+ if (autoStageAll || /\bgit\s+add\s+(?:--\s+)?vitest\.config\.ts\b/.test(commands)) {
3932
+ context.report({ node, message: ".husky/pre-commit must not auto-stage vitest.config.ts." });
3933
+ }
3934
+ if (existsSync4(path30.join(context.cwd, "vulyk.config.ts"))) {
3935
+ const syncIndex = commands.search(/\bnpx\s+vulyk\s+sync\b/);
3936
+ const agentsIndex = commands.search(/\bnpx\s+vulyk\s+agents\b/);
3937
+ const stagedIndex = commands.indexOf("lint-staged");
3938
+ if (syncIndex < 0 || agentsIndex <= syncIndex || stagedIndex <= agentsIndex) {
3939
+ context.report({
3940
+ node,
3941
+ message: ".husky/pre-commit must run npx vulyk sync and npx vulyk agents before lint-staged."
3942
+ });
3943
+ }
3944
+ const stageIndex = commands.search(/\bnpx\s+vulyk\s+stage\b/);
3945
+ if (stageIndex <= agentsIndex || stageIndex >= stagedIndex) {
3946
+ context.report({
3947
+ node,
3948
+ message: ".husky/pre-commit must run npx vulyk stage after agents and before lint-staged."
3949
+ });
3950
+ }
3951
+ }
3850
3952
  if (!content.includes("libyear --limit-major-individual=1")) {
3851
3953
  context.report({ node, message: ".husky/pre-commit must run npx libyear --limit-major-individual=1." });
3852
3954
  }
@@ -4442,7 +4544,7 @@ var localeDottedPathRule = {
4442
4544
  schema: [],
4443
4545
  type: "problem",
4444
4546
  docs: {
4445
- description: "Require reading namespaced locales through their full dotted path."
4547
+ description: "Require direct global and feature locale access without destructuring."
4446
4548
  }
4447
4549
  },
4448
4550
  create(context) {
@@ -4463,7 +4565,7 @@ var localeDottedPathRule = {
4463
4565
  if (valueName) {
4464
4566
  context.report({
4465
4567
  node,
4466
- 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.`
4467
4569
  });
4468
4570
  }
4469
4571
  }
@@ -4522,10 +4624,15 @@ var ROLE_POSTFIXES = /* @__PURE__ */ new Set([
4522
4624
  ]);
4523
4625
  var CAMEL_CASE = /^[a-z][a-zA-Z0-9]*$/;
4524
4626
  var ENGLISH = /^[A-Za-z0-9_]*$/;
4525
- function isLocalesFile(filename) {
4627
+ function dictionaryName(filename) {
4526
4628
  const segments = path35.resolve(filename).split(path35.sep);
4527
4629
  const srcIdx = segments.lastIndexOf("src");
4528
- 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;
4529
4636
  }
4530
4637
  function keyName(key) {
4531
4638
  if (key.type === "Identifier") return key.name;
@@ -4582,31 +4689,28 @@ var localeKeyShapeRule = {
4582
4689
  }
4583
4690
  },
4584
4691
  create(context) {
4585
- if (!isLocalesFile(context.filename)) return {};
4586
- function visitObject(node, namespace) {
4692
+ const dictionary = dictionaryName(context.filename) ?? "";
4693
+ if (!dictionary) return {};
4694
+ function visitObject(node) {
4587
4695
  for (const property of node.properties) {
4588
4696
  if (property.type !== "Property") continue;
4589
4697
  const name = keyName(property.key);
4590
4698
  if (name === void 0) continue;
4591
4699
  const nested = localeObject(property.value);
4592
4700
  if (nested) {
4593
- if (namespace !== void 0) {
4594
- reportFor(
4595
- context,
4596
- property,
4597
- `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`
4598
- );
4599
- } else {
4600
- visitObject(nested, name);
4601
- }
4602
- } 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) {
4603
4707
  checkKey(context, property, name);
4604
4708
  }
4605
4709
  }
4606
4710
  }
4607
4711
  return {
4608
4712
  VariableDeclarator(node) {
4609
- if (node.id.type !== "Identifier" || node.id.name !== "locales") return;
4713
+ if (node.id.type !== "Identifier" || node.id.name !== dictionary) return;
4610
4714
  const root = localeObject(node.init);
4611
4715
  if (!root) return;
4612
4716
  visitObject(root);
@@ -4616,135 +4720,307 @@ var localeKeyShapeRule = {
4616
4720
  };
4617
4721
 
4618
4722
  // eslint/rules/locale-placement.ts
4619
- 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";
4620
4729
  import path36 from "path";
4621
4730
  import ts6 from "typescript";
4622
- var LOCALE_ACCESS = /\blocales\.(?<key>[A-Za-z_$][\w$]*)/g;
4623
4731
  var camelCase = (name) => name.replace(/-[a-z]/g, (match) => match.slice(1).toUpperCase());
4624
- var FORCED_TOP_LEVEL = /* @__PURE__ */ new Set(["app", "shared", "compositions", "config"]);
4625
- function forcesTopLevel(segments) {
4626
- 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;
4627
4737
  }
4628
- function localePlacement(text) {
4629
- const sourceFile = ts6.createSourceFile("locales.ts", text, ts6.ScriptTarget.Latest, true, ts6.ScriptKind.TS);
4630
- for (const statement of sourceFile.statements) {
4738
+ function exportedDictionary(source, name) {
4739
+ for (const statement of source.statements) {
4631
4740
  if (!ts6.isVariableStatement(statement)) continue;
4632
- const isExported3 = (ts6.getModifiers(statement) ?? []).some(
4741
+ const exported = (ts6.getModifiers(statement) ?? []).some(
4633
4742
  (modifier) => modifier.kind === ts6.SyntaxKind.ExportKeyword
4634
4743
  );
4635
- if (!isExported3) continue;
4744
+ if (!exported || !(statement.declarationList.flags & ts6.NodeFlags.Const)) continue;
4745
+ if (statement.declarationList.declarations.length !== 1) continue;
4636
4746
  for (const declaration of statement.declarationList.declarations) {
4637
- if (!ts6.isIdentifier(declaration.name) || declaration.name.text !== "locales") continue;
4638
- if (!declaration.initializer || !ts6.isObjectLiteralExpression(declaration.initializer)) continue;
4639
- const placement = /* @__PURE__ */ new Map();
4640
- for (const property of declaration.initializer.properties) {
4641
- if (!ts6.isPropertyAssignment(property)) continue;
4642
- let name;
4643
- if (ts6.isIdentifier(property.name)) name = property.name.text;
4644
- else if (ts6.isStringLiteral(property.name)) name = property.name.text;
4645
- if (name === void 0) continue;
4646
- const line = sourceFile.getLineAndCharacterOfPosition(property.getStart(sourceFile)).line + 1;
4647
- placement.set(name, {
4648
- kind: ts6.isObjectLiteralExpression(property.initializer) ? "nested" : "top",
4649
- line
4650
- });
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;
4651
4750
  }
4652
- return placement;
4653
4751
  }
4654
4752
  }
4655
4753
  return void 0;
4656
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
+ }
4657
4915
  var localePlacementRule = {
4658
4916
  meta: {
4659
4917
  schema: [],
4660
4918
  type: "problem",
4661
4919
  docs: {
4662
- 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."
4663
4921
  }
4664
4922
  },
4665
4923
  create(context) {
4666
4924
  const sourceRoot = sourceRootOf(context);
4667
- const file = path36.resolve(context.filename);
4925
+ const file = path37.resolve(context.filename);
4668
4926
  const segments = segmentsOf(file, sourceRoot);
4669
4927
  if (segments.length === 0) return {};
4670
4928
  const index = getProjectIndex(sourceRoot);
4671
4929
  if (!index) return {};
4672
4930
  const localesFile = [...index.modules.keys()].find((candidate) => {
4673
- const candidateSegments = segmentsOf(candidate, sourceRoot);
4674
- 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";
4675
4933
  });
4676
4934
  if (!localesFile || file !== localesFile) return {};
4677
- const placement = localePlacement(readFileSync7(localesFile, "utf8"));
4678
- if (!placement) return {};
4679
- const keyReaders = /* @__PURE__ */ new Map();
4680
- const keyFeatures = /* @__PURE__ */ new Map();
4681
- 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();
4682
4939
  for (const [candidateFile, module] of index.modules) {
4683
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
+ }
4684
4951
  const importsLocales = module.imports.some(
4685
4952
  (moduleImport) => resolveSpecifier(candidateFile, moduleImport.specifier, sourceRoot) === localesFile
4686
4953
  );
4687
4954
  if (!importsLocales) continue;
4688
- const candidateSegments = segmentsOf(candidateFile, sourceRoot);
4689
- for (const match of readFileSync7(candidateFile, "utf8").matchAll(LOCALE_ACCESS)) {
4690
- const key = match.groups?.key;
4691
- if (key === void 0) continue;
4692
- const readers = keyReaders.get(key) ?? /* @__PURE__ */ new Set();
4693
- readers.add(candidateFile);
4694
- keyReaders.set(key, readers);
4695
- if (candidateSegments[0] === "features" && candidateSegments.length >= 2) {
4696
- const features = keyFeatures.get(key) ?? /* @__PURE__ */ new Set();
4697
- features.add(candidateSegments[1] ?? "");
4698
- keyFeatures.set(key, features);
4699
- } else if (forcesTopLevel(candidateSegments)) {
4700
- 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
+ );
4701
4992
  }
4702
4993
  }
4703
4994
  }
4704
- const findings = [];
4705
- for (const [key, readers] of keyReaders) {
4706
- const features = keyFeatures.get(key) ?? /* @__PURE__ */ new Set();
4707
- const shared = features.size > 1 || keyForcedTopLevel.has(key);
4708
- const current = placement.get(key);
4709
- if (shared) {
4710
- if (current?.kind === "nested") {
4711
- findings.push({
4712
- line: current.line,
4713
- 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`
4714
- });
4715
- }
4716
- 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);
4717
5001
  }
4718
- if (features.size !== 1) continue;
4719
- const featureName = [...features][0] ?? "";
4720
- const expected = camelCase(featureName);
4721
- if (current?.kind === "top") {
4722
- findings.push({
4723
- line: current.line,
4724
- 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`
4725
- });
4726
- } else if (current?.kind === "nested" && key !== expected) {
4727
- findings.push({
4728
- line: current.line,
4729
- 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`
4730
- });
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
+ );
4731
5009
  }
4732
5010
  }
4733
5011
  if (findings.length === 0) return {};
4734
5012
  return {
4735
5013
  Program(node) {
4736
- for (const finding of findings) {
4737
- context.report({ node, loc: { line: finding.line, column: 0 }, message: finding.message });
4738
- }
5014
+ for (const message of findings) context.report({ node, message });
4739
5015
  }
4740
5016
  };
4741
5017
  }
4742
5018
  };
4743
5019
 
4744
5020
  // eslint/rules/locales-location.ts
4745
- import path37 from "path";
4746
- function isLocalesFile2(filename) {
4747
- 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);
4748
5024
  const srcIdx = segments.lastIndexOf("src");
4749
5025
  return srcIdx !== -1 && segments[srcIdx + 1] === "locales";
4750
5026
  }
@@ -4822,9 +5098,9 @@ var localesLocationRule = {
4822
5098
  }
4823
5099
  },
4824
5100
  create(context) {
4825
- if (isLocalesFile2(context.filename) || isTestFile(context.filename)) return {};
5101
+ if (isLocalesFile(context.filename) || isTestFile(context.filename)) return {};
4826
5102
  const filename = context.filename;
4827
- const segments = path37.resolve(filename).split(path37.sep);
5103
+ const segments = path38.resolve(filename).split(path38.sep);
4828
5104
  const srcIdx = segments.lastIndexOf("src");
4829
5105
  if (srcIdx === -1) return {};
4830
5106
  const folder = segments[srcIdx + 1];
@@ -4909,7 +5185,7 @@ var localesLocationRule = {
4909
5185
  };
4910
5186
 
4911
5187
  // eslint/rules/named-exports.ts
4912
- import path38 from "path";
5188
+ import path39 from "path";
4913
5189
  var FRAMEWORK_DEFAULT_EXPORT_FILES = /* @__PURE__ */ new Set([
4914
5190
  // App Router routing files
4915
5191
  "default",
@@ -4931,9 +5207,9 @@ var FRAMEWORK_DEFAULT_EXPORT_FILES = /* @__PURE__ */ new Set([
4931
5207
  "twitter-image"
4932
5208
  ]);
4933
5209
  function isFrameworkDefaultExportFile(filename) {
4934
- const normalized = filename.replaceAll(path38.sep, "/");
5210
+ const normalized = filename.replaceAll(path39.sep, "/");
4935
5211
  if (!normalized.includes("/src/app/")) return false;
4936
- const basename = path38.basename(filename, path38.extname(filename));
5212
+ const basename = path39.basename(filename, path39.extname(filename));
4937
5213
  return FRAMEWORK_DEFAULT_EXPORT_FILES.has(basename);
4938
5214
  }
4939
5215
  var namedExportsRule = {
@@ -5101,12 +5377,12 @@ var noArbitraryTailwindRule = {
5101
5377
  };
5102
5378
 
5103
5379
  // eslint/rules/no-inline-runtime-literal.ts
5104
- import path40 from "path";
5380
+ import path41 from "path";
5105
5381
 
5106
5382
  // eslint/project/semantic-literals.ts
5107
- import { readFileSync as readFileSync8 } from "fs";
5108
- import path39 from "path";
5109
- import ts7 from "typescript";
5383
+ import { readFileSync as readFileSync9 } from "fs";
5384
+ import path40 from "path";
5385
+ import ts8 from "typescript";
5110
5386
  var excludedProperties = /* @__PURE__ */ new Set([
5111
5387
  "label",
5112
5388
  "title",
@@ -5144,33 +5420,33 @@ var columnMethods = /* @__PURE__ */ new Set([
5144
5420
  var eventMethods = /* @__PURE__ */ new Set(["emit", "on", "off", "once", "addListener", "removeListener"]);
5145
5421
  var ignoredNumbers = /* @__PURE__ */ new Set([-1, 0, 1]);
5146
5422
  function isProductionSource(file, root) {
5147
- const parts = path39.relative(root, file).split(path39.sep);
5148
- 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"));
5149
5425
  }
5150
5426
  function featureOf(file, root) {
5151
- const parts = path39.relative(root, file).split(path39.sep);
5427
+ const parts = path40.relative(root, file).split(path40.sep);
5152
5428
  if (parts[0] === "features" && parts[1]) return `feature:${parts[1]}`;
5153
5429
  return `layer:${parts[0] ?? "src"}`;
5154
5430
  }
5155
5431
  function nameOf(property) {
5156
- if (ts7.isIdentifier(property) || ts7.isStringLiteral(property)) return property.text;
5432
+ if (ts8.isIdentifier(property) || ts8.isStringLiteral(property)) return property.text;
5157
5433
  return void 0;
5158
5434
  }
5159
5435
  function literalOf(node) {
5160
- if (ts7.isStringLiteral(node)) return node.text;
5161
- if (ts7.isNumericLiteral(node)) return Number(node.text.replaceAll("_", ""));
5162
- 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)) {
5163
5439
  return -Number(node.operand.text.replaceAll("_", ""));
5164
5440
  }
5165
5441
  return void 0;
5166
5442
  }
5167
5443
  function isLiteralRoot(node) {
5168
- if (ts7.isPrefixUnaryExpression(node)) return literalOf(node) !== void 0;
5169
- 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);
5170
5446
  }
5171
5447
  function invocation(node) {
5172
- if (ts7.isIdentifier(node.expression)) return { method: node.expression.text };
5173
- if (ts7.isPropertyAccessExpression(node.expression)) {
5448
+ if (ts8.isIdentifier(node.expression)) return { method: node.expression.text };
5449
+ if (ts8.isPropertyAccessExpression(node.expression)) {
5174
5450
  const receiver = node.expression.expression.getText();
5175
5451
  if (!/^[A-Za-z_$][\w$]*(?:\.[A-Za-z_$][\w$]*)?$/.test(receiver)) return void 0;
5176
5452
  return { method: node.expression.name.text, receiver };
@@ -5178,7 +5454,7 @@ function invocation(node) {
5178
5454
  return void 0;
5179
5455
  }
5180
5456
  function isPathname(node) {
5181
- return ts7.isPropertyAccessExpression(node) && node.name.text === "pathname";
5457
+ return ts8.isPropertyAccessExpression(node) && node.name.text === "pathname";
5182
5458
  }
5183
5459
  function contextFor(node, value, file, root) {
5184
5460
  if (typeof value === "number" && ignoredNumbers.has(value)) return void 0;
@@ -5187,7 +5463,7 @@ function contextFor(node, value, file, root) {
5187
5463
  const scope = featureOf(file, root);
5188
5464
  const isApiRoute = typeof value === "string" && value.startsWith("/api/") && !/[?&#\s]/.test(value);
5189
5465
  const route = () => ({ role: "api-route", family: "api-route" });
5190
- if (ts7.isPropertyAssignment(parent) && parent.initializer === node) {
5466
+ if (ts8.isPropertyAssignment(parent) && parent.initializer === node) {
5191
5467
  const name = nameOf(parent.name);
5192
5468
  if (!name) return void 0;
5193
5469
  if (name === "path" && isApiRoute) return route();
@@ -5196,14 +5472,14 @@ function contextFor(node, value, file, root) {
5196
5472
  if (isApiRoute && /route|path|endpoint/i.test(name)) return route();
5197
5473
  return { role: `property:${name}:${scope}`, family: `property:${name}` };
5198
5474
  }
5199
- if (ts7.isVariableDeclaration(parent) && parent.initializer === node && ts7.isIdentifier(parent.name)) {
5475
+ if (ts8.isVariableDeclaration(parent) && parent.initializer === node && ts8.isIdentifier(parent.name)) {
5200
5476
  if (typeof value === "number") return void 0;
5201
5477
  const name = parent.name.text;
5202
5478
  if (excludedProperties.has(name) || !semanticVariableName.test(name)) return void 0;
5203
5479
  if (isApiRoute && /route|path|endpoint/i.test(name)) return route();
5204
5480
  return { role: `variable:${name}:${scope}`, family: `variable:${name}` };
5205
5481
  }
5206
- if (ts7.isCallExpression(parent)) {
5482
+ if (ts8.isCallExpression(parent)) {
5207
5483
  const position = parent.arguments.findIndex((argument) => argument === node);
5208
5484
  if (position < 0) return void 0;
5209
5485
  const call = invocation(parent);
@@ -5222,45 +5498,45 @@ function contextFor(node, value, file, root) {
5222
5498
  return { role: `column:${scope}`, family: "column" };
5223
5499
  }
5224
5500
  }
5225
- 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))) {
5226
5502
  return route();
5227
5503
  }
5228
- 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)) {
5229
5505
  return route();
5230
5506
  }
5231
5507
  return void 0;
5232
5508
  }
5233
5509
  function isExported2(node) {
5234
- 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);
5235
5511
  }
5236
5512
  function parse(file, root, output) {
5237
5513
  if (!isProductionSource(file, root)) return;
5238
- const source = ts7.createSourceFile(
5514
+ const source = ts8.createSourceFile(
5239
5515
  file,
5240
- readFileSync8(file, "utf8"),
5241
- ts7.ScriptTarget.Latest,
5516
+ readFileSync9(file, "utf8"),
5517
+ ts8.ScriptTarget.Latest,
5242
5518
  true,
5243
- 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
5244
5520
  );
5245
- const inConstants = path39.relative(root, file).split(path39.sep).includes("constants");
5521
+ const inConstants = path40.relative(root, file).split(path40.sep).includes("constants");
5246
5522
  for (const statement of source.statements) {
5247
- if (inConstants && ts7.isEnumDeclaration(statement) && isExported2(statement)) {
5523
+ if (inConstants && ts8.isEnumDeclaration(statement) && isExported2(statement)) {
5248
5524
  for (const member of statement.members) {
5249
5525
  const value = member.initializer && literalOf(member.initializer);
5250
- const memberName9 = nameOf(member.name);
5251
- if (value === void 0 || !memberName9) continue;
5526
+ const memberName10 = nameOf(member.name);
5527
+ if (value === void 0 || !memberName10) continue;
5252
5528
  output.canonicals.push({
5253
5529
  file,
5254
- name: memberName9,
5530
+ name: memberName10,
5255
5531
  owner: statement.name.text,
5256
5532
  kind: typeof value === "string" ? "string" : "number",
5257
5533
  value
5258
5534
  });
5259
5535
  }
5260
5536
  }
5261
- if (inConstants && ts7.isVariableStatement(statement) && isExported2(statement)) {
5537
+ if (inConstants && ts8.isVariableStatement(statement) && isExported2(statement)) {
5262
5538
  for (const declaration of statement.declarationList.declarations) {
5263
- if (!ts7.isIdentifier(declaration.name) || !declaration.initializer) continue;
5539
+ if (!ts8.isIdentifier(declaration.name) || !declaration.initializer) continue;
5264
5540
  const value = literalOf(declaration.initializer);
5265
5541
  if (value === void 0) continue;
5266
5542
  output.canonicals.push({
@@ -5279,7 +5555,7 @@ function parse(file, root, output) {
5279
5555
  const semantic = contextFor(node, value, file, root);
5280
5556
  if (semantic) {
5281
5557
  const declaration = node.parent;
5282
- 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));
5283
5559
  if ((!inConstants || semantic.family === "api-route") && !isCanonicalDefinition) {
5284
5560
  const position = source.getLineAndCharacterOfPosition(node.getStart(source));
5285
5561
  output.uses.push({
@@ -5294,7 +5570,7 @@ function parse(file, root, output) {
5294
5570
  }
5295
5571
  }
5296
5572
  }
5297
- ts7.forEachChild(node, visit);
5573
+ ts8.forEachChild(node, visit);
5298
5574
  };
5299
5575
  visit(source);
5300
5576
  }
@@ -5314,8 +5590,8 @@ function getSemanticLiteralIndex(index) {
5314
5590
  }
5315
5591
 
5316
5592
  // eslint/rules/no-inline-runtime-literal.ts
5317
- var DOC4 = "See docs/next-codebase-guide/rules/constants-rule.md";
5318
- 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}`;
5319
5595
  function isClassNameProp(node) {
5320
5596
  let current = node;
5321
5597
  while (current.parent) {
@@ -5328,15 +5604,43 @@ function isClassNameProp(node) {
5328
5604
  }
5329
5605
  return false;
5330
5606
  }
5331
- function containsInlineString(node) {
5332
- if (typeof node !== "object" || node === null || !("type" in node)) return false;
5333
- if (node.type === "TemplateLiteral") return true;
5334
- if (node.type === "Literal") return "value" in node && typeof node.value === "string";
5335
- if (node.type === "BinaryExpression") {
5336
- return "left" in node && containsInlineString(node.left) || "right" in node && containsInlineString(node.right);
5337
- }
5338
- if (node.type === "TSAsExpression" || node.type === "TSSatisfiesExpression") {
5339
- 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";
5340
5644
  }
5341
5645
  return false;
5342
5646
  }
@@ -5346,8 +5650,7 @@ function isNamedValue(node) {
5346
5650
  const parent2 = current.parent;
5347
5651
  const isTypeWrapper = parent2.type === "TSAsExpression" || parent2.type === "TSSatisfiesExpression";
5348
5652
  const isSignedNumber = parent2.type === "UnaryExpression" && parent2.argument === current && (parent2.operator === "-" || parent2.operator === "+");
5349
- const isArithmetic = parent2.type === "BinaryExpression" && typeof parent2.operator === "string" && ["+", "-", "*", "/", "%", "**", "<<", ">>", ">>>", "&", "|", "^"].includes(parent2.operator) && !containsInlineString(parent2.left) && !containsInlineString(parent2.right);
5350
- if (!isTypeWrapper && !isSignedNumber && !isArithmetic) break;
5653
+ if (!isTypeWrapper && !isSignedNumber) break;
5351
5654
  current = parent2;
5352
5655
  }
5353
5656
  const parent = current.parent;
@@ -5360,6 +5663,7 @@ function isNamedValue(node) {
5360
5663
  function isSyntacticString(node) {
5361
5664
  const parent = node.parent;
5362
5665
  if (!parent) return false;
5666
+ if (parent.type === "TSModuleDeclaration" && parent.id === node) return true;
5363
5667
  if (parent.type === "ImportDeclaration" || parent.type === "ExportNamedDeclaration" || parent.type === "ExportAllDeclaration" || parent.type === "ImportExpression" || parent.type === "TSLiteralType" || parent.type === "TSExternalModuleReference") {
5364
5668
  return true;
5365
5669
  }
@@ -5370,27 +5674,25 @@ function isSyntacticString(node) {
5370
5674
  return false;
5371
5675
  }
5372
5676
  function isRuntimeMockSource(file, root) {
5373
- const parts = path40.relative(root, file).split(path40.sep);
5374
- 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));
5375
5679
  }
5376
5680
  function isCanonicalLocaleString(node, root, file) {
5377
- if (path40.relative(root, file) !== path40.join("locales", "index.ts")) return false;
5378
- let current = node;
5379
- let depth = 0;
5380
- while (current.parent?.type === "Property" && current.parent.value === current) {
5381
- const object = current.parent.parent;
5382
- if (object?.type !== "ObjectExpression") return false;
5383
- current = object;
5384
- depth += 1;
5385
- }
5386
- 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;
5387
5690
  while ((current.parent?.type === "TSAsExpression" || current.parent?.type === "TSSatisfiesExpression") && current.parent.expression === current) {
5388
5691
  current = current.parent;
5389
5692
  }
5390
5693
  const declaration = current.parent;
5391
- if (declaration?.type !== "VariableDeclarator" || declaration.init !== current) return false;
5392
- const id = declaration.id;
5393
- 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";
5394
5696
  }
5395
5697
  var noInlineRuntimeLiteralRule = {
5396
5698
  meta: {
@@ -5400,8 +5702,8 @@ var noInlineRuntimeLiteralRule = {
5400
5702
  },
5401
5703
  create(context) {
5402
5704
  const root = sourceRootOf(context);
5403
- const file = path40.resolve(context.filename);
5404
- 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)) {
5405
5707
  return {};
5406
5708
  }
5407
5709
  return {
@@ -5409,7 +5711,7 @@ var noInlineRuntimeLiteralRule = {
5409
5711
  if (typeof node.value !== "string" && typeof node.value !== "number" && typeof node.value !== "bigint" && !("bigint" in node && typeof node.bigint === "string")) {
5410
5712
  return;
5411
5713
  }
5412
- 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)) {
5413
5715
  return;
5414
5716
  }
5415
5717
  context.report({ node, message: MESSAGE2 });
@@ -5448,7 +5750,7 @@ function isStaticValue(value) {
5448
5750
  }
5449
5751
  return false;
5450
5752
  }
5451
- function propertyName2(property) {
5753
+ function propertyName3(property) {
5452
5754
  if (!property.computed && property.key.type === "Identifier") return property.key.name;
5453
5755
  if (property.key.type === "Literal" && typeof property.key.value === "string") return property.key.value;
5454
5756
  return void 0;
@@ -5456,7 +5758,7 @@ function propertyName2(property) {
5456
5758
  function findStaticDeclaration(expression) {
5457
5759
  for (const property of expression.properties) {
5458
5760
  if (property.type !== "Property" || property.kind !== "init") continue;
5459
- const name = propertyName2(property);
5761
+ const name = propertyName3(property);
5460
5762
  if (!name) continue;
5461
5763
  if (isStaticValue(property.value)) return name;
5462
5764
  }
@@ -5498,8 +5800,8 @@ var noLiteralInlineStyleRule = {
5498
5800
  };
5499
5801
 
5500
5802
  // eslint/rules/no-mixed-concerns.ts
5501
- import { readFileSync as readFileSync9 } from "fs";
5502
- import path41 from "path";
5803
+ import { readFileSync as readFileSync10 } from "fs";
5804
+ import path42 from "path";
5503
5805
  var noMixedConcernsRule = {
5504
5806
  meta: {
5505
5807
  schema: [],
@@ -5523,7 +5825,7 @@ var noMixedConcernsRule = {
5523
5825
  if (components.length > 1) return;
5524
5826
  const componentName = components[0]?.name;
5525
5827
  if (!componentName) return;
5526
- const file = path41.resolve(context.filename);
5828
+ const file = path42.resolve(context.filename);
5527
5829
  const sourceRoot = sourceRootOf(context);
5528
5830
  const index = getProjectIndex(sourceRoot);
5529
5831
  const componentConsumers = index?.symbolConsumers.get(symbolKey(file, componentName)) ?? /* @__PURE__ */ new Set();
@@ -5534,6 +5836,7 @@ var noMixedConcernsRule = {
5534
5836
  if (name === componentName) return;
5535
5837
  if (isNextPageOrLayout) {
5536
5838
  if (["metadata", "viewport", "generateMetadata", "generateViewport"].includes(name)) return;
5839
+ if (name === "generateStaticParams" && /\[[^\]]+\]/.test(context.filename)) return;
5537
5840
  context.report({
5538
5841
  loc,
5539
5842
  message: `Next.js page/layout files cannot export "${name}". Use a separate module for supporting values.`
@@ -5567,7 +5870,7 @@ var noMixedConcernsRule = {
5567
5870
  continue;
5568
5871
  }
5569
5872
  const target = typeof statement.source?.value === "string" ? resolveSpecifier(file, statement.source.value, sourceRoot) : void 0;
5570
- 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) : [];
5571
5874
  for (const specifier of statement.specifiers) {
5572
5875
  if (/^type\b/.test(context.sourceCode.getText(specifier))) continue;
5573
5876
  if (specifier.local.type !== "Identifier") continue;
@@ -5601,11 +5904,11 @@ var noMixedConcernsRule = {
5601
5904
  };
5602
5905
 
5603
5906
  // eslint/rules/no-redundant-alias.ts
5604
- import path43 from "path";
5907
+ import path44 from "path";
5605
5908
 
5606
5909
  // eslint/rules/contract-ownership.ts
5607
- import path42 from "path";
5608
- import ts8 from "typescript";
5910
+ import path43 from "path";
5911
+ import ts9 from "typescript";
5609
5912
  function isTsProgram(value) {
5610
5913
  return typeof value === "object" && value !== null && "getTypeChecker" in value && typeof value.getTypeChecker === "function" && "getSourceFiles" in value && typeof value.getSourceFiles === "function";
5611
5914
  }
@@ -5623,8 +5926,8 @@ function normalizePath(value) {
5623
5926
  return value.replaceAll("\\", "/").toLowerCase();
5624
5927
  }
5625
5928
  function isWithin2(root, file) {
5626
- const relative = path42.relative(root, file);
5627
- return relative === "" || !relative.startsWith("..") && !path42.isAbsolute(relative);
5929
+ const relative = path43.relative(root, file);
5930
+ return relative === "" || !relative.startsWith("..") && !path43.isAbsolute(relative);
5628
5931
  }
5629
5932
  function mergeOwnership(values) {
5630
5933
  if (values.length === 0 || values.includes("unknown")) return "unknown";
@@ -5639,11 +5942,11 @@ function endpointOwnership(pathValue) {
5639
5942
  return "unknown";
5640
5943
  }
5641
5944
  function resolvedSymbol(checker, symbol) {
5642
- return symbol.flags === ts8.SymbolFlags.Alias ? checker.getAliasedSymbol(symbol) : symbol;
5945
+ return symbol.flags === ts9.SymbolFlags.Alias ? checker.getAliasedSymbol(symbol) : symbol;
5643
5946
  }
5644
- function propertyName3(node) {
5947
+ function propertyName4(node) {
5645
5948
  if (!node) return void 0;
5646
- 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;
5647
5950
  return void 0;
5648
5951
  }
5649
5952
  var ContractOwnershipIndex = class {
@@ -5667,7 +5970,7 @@ var ContractOwnershipIndex = class {
5667
5970
  }
5668
5971
  if (declarations.length > 0) return this.endpointFromDeclarations(declarations);
5669
5972
  let object;
5670
- if (ts8.isPropertyAccessExpression(node) || ts8.isElementAccessExpression(node)) object = node.expression;
5973
+ if (ts9.isPropertyAccessExpression(node) || ts9.isElementAccessExpression(node)) object = node.expression;
5671
5974
  if (!object) return { kind: "missing", ownership: "unknown" };
5672
5975
  const type = this.checker.getTypeAtLocation(object);
5673
5976
  const typeDeclarations = this.typeDeclarations(type);
@@ -5675,7 +5978,7 @@ var ContractOwnershipIndex = class {
5675
5978
  return this.endpointFromDeclarations(typeDeclarations);
5676
5979
  }
5677
5980
  sourceBinding(node, name) {
5678
- if (!ts8.isVariableDeclaration(node) || !node.initializer) {
5981
+ if (!ts9.isVariableDeclaration(node) || !node.initializer) {
5679
5982
  return { kind: "missing", ownership: "unknown" };
5680
5983
  }
5681
5984
  const sourceType = this.checker.getTypeAtLocation(node.initializer);
@@ -5684,11 +5987,11 @@ var ContractOwnershipIndex = class {
5684
5987
  return this.endpointFromDeclarations(declarations);
5685
5988
  }
5686
5989
  targetProperty(node, name) {
5687
- if (!ts8.isPropertyAssignment(node) && !ts8.isShorthandPropertyAssignment(node)) {
5990
+ if (!ts9.isPropertyAssignment(node) && !ts9.isShorthandPropertyAssignment(node)) {
5688
5991
  return { kind: "missing", ownership: "unknown" };
5689
5992
  }
5690
5993
  const object = node.parent;
5691
- if (!ts8.isObjectLiteralExpression(object)) return { kind: "missing", ownership: "unknown" };
5994
+ if (!ts9.isObjectLiteralExpression(object)) return { kind: "missing", ownership: "unknown" };
5692
5995
  const contextualType = this.checker.getContextualType(object);
5693
5996
  if (!contextualType) return { kind: "missing", ownership: "unknown" };
5694
5997
  const declarations = this.propertyDeclarations(contextualType, name);
@@ -5696,8 +5999,8 @@ var ContractOwnershipIndex = class {
5696
5999
  return this.endpointFromDeclarations(declarations);
5697
6000
  }
5698
6001
  memberNameSymbol(node) {
5699
- if (ts8.isPropertyAccessExpression(node)) return this.checker.getSymbolAtLocation(node.name);
5700
- 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);
5701
6004
  return void 0;
5702
6005
  }
5703
6006
  propertyDeclarations(type, name) {
@@ -5727,14 +6030,14 @@ var ContractOwnershipIndex = class {
5727
6030
  if (declarations.some((declaration) => this.isDataContractField(declaration))) {
5728
6031
  return { kind: "data-contract", ownership };
5729
6032
  }
5730
- if (declarations.some((declaration) => ts8.isPropertySignature(declaration) || ts8.isPropertyDeclaration(declaration))) {
6033
+ if (declarations.some((declaration) => ts9.isPropertySignature(declaration) || ts9.isPropertyDeclaration(declaration))) {
5731
6034
  return { kind: "typed-local", ownership };
5732
6035
  }
5733
6036
  return { kind: "non-contract", ownership };
5734
6037
  }
5735
6038
  isDataContractField(declaration) {
5736
6039
  if (this.isZodSchemaField(declaration)) return true;
5737
- if (!ts8.isPropertySignature(declaration) && !ts8.isPropertyDeclaration(declaration)) return false;
6040
+ if (!ts9.isPropertySignature(declaration) && !ts9.isPropertyDeclaration(declaration)) return false;
5738
6041
  const fileName = normalizePath(declaration.getSourceFile().fileName);
5739
6042
  return /(?:^|\/)database(?:[-.]generated)?\.ts$/u.test(fileName);
5740
6043
  }
@@ -5743,10 +6046,10 @@ var ContractOwnershipIndex = class {
5743
6046
  return this.checker.getPropertyOfType(type, "_zod") !== void 0 && this.checker.getPropertyOfType(type, "parse") !== void 0 && this.checker.getPropertyOfType(type, "safeParse") !== void 0;
5744
6047
  }
5745
6048
  isZodSchemaField(declaration) {
5746
- if (!ts8.isPropertyAssignment(declaration)) return false;
6049
+ if (!ts9.isPropertyAssignment(declaration)) return false;
5747
6050
  let current = declaration.parent;
5748
- while (!ts8.isSourceFile(current)) {
5749
- 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")) {
5750
6053
  return true;
5751
6054
  }
5752
6055
  current = current.parent;
@@ -5764,12 +6067,12 @@ var ContractOwnershipIndex = class {
5764
6067
  const normalized = normalizePath(fileName);
5765
6068
  if (/\/typescript\/lib\/lib\.[^/]+\.d\.ts$/u.test(normalized)) return "platform";
5766
6069
  if (normalized.includes("/node_modules/")) return "third-party";
5767
- if (isWithin2(this.cwd, path42.resolve(fileName))) return "first-party";
6070
+ if (isWithin2(this.cwd, path43.resolve(fileName))) return "first-party";
5768
6071
  return "unknown";
5769
6072
  }
5770
6073
  schemaOwnership(declaration) {
5771
6074
  let current = declaration;
5772
- while (!ts8.isSourceFile(current)) {
6075
+ while (!ts9.isSourceFile(current)) {
5773
6076
  const ownership = this.schemaNodeOwnership.get(current);
5774
6077
  if (ownership !== void 0) return ownership;
5775
6078
  current = current.parent;
@@ -5778,31 +6081,31 @@ var ContractOwnershipIndex = class {
5778
6081
  }
5779
6082
  indexApiContracts() {
5780
6083
  for (const sourceFile of this.program.getSourceFiles()) {
5781
- if (sourceFile.isDeclarationFile || !isWithin2(this.cwd, path42.resolve(sourceFile.fileName))) continue;
6084
+ if (sourceFile.isDeclarationFile || !isWithin2(this.cwd, path43.resolve(sourceFile.fileName))) continue;
5782
6085
  const visit = (node) => {
5783
- if (ts8.isCallExpression(node) && this.isDefineApiContractCall(node)) this.indexApiContractCall(node);
5784
- ts8.forEachChild(node, visit);
6086
+ if (ts9.isCallExpression(node) && this.isDefineApiContractCall(node)) this.indexApiContractCall(node);
6087
+ ts9.forEachChild(node, visit);
5785
6088
  };
5786
6089
  visit(sourceFile);
5787
6090
  }
5788
6091
  }
5789
6092
  isDefineApiContractCall(node) {
5790
- if (ts8.isIdentifier(node.expression)) return node.expression.text === "defineApiContract";
5791
- 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";
5792
6095
  }
5793
6096
  indexApiContractCall(node) {
5794
6097
  const argument = node.arguments[0];
5795
- if (!argument || !ts8.isObjectLiteralExpression(argument)) return;
6098
+ if (!argument || !ts9.isObjectLiteralExpression(argument)) return;
5796
6099
  let pathExpression;
5797
6100
  const schemaExpressions = [];
5798
6101
  for (const property of argument.properties) {
5799
- if (ts8.isPropertyAssignment(property)) {
5800
- const name = propertyName3(property.name);
6102
+ if (ts9.isPropertyAssignment(property)) {
6103
+ const name = propertyName4(property.name);
5801
6104
  if (name === "path") pathExpression = property.initializer;
5802
6105
  if (name === "requestSchema" || name === "responseSchema") schemaExpressions.push(property.initializer);
5803
6106
  continue;
5804
6107
  }
5805
- if (ts8.isShorthandPropertyAssignment(property)) {
6108
+ if (ts9.isShorthandPropertyAssignment(property)) {
5806
6109
  const name = property.name.text;
5807
6110
  if (name === "path") pathExpression = property.name;
5808
6111
  if (name === "requestSchema" || name === "responseSchema") schemaExpressions.push(property.name);
@@ -5816,13 +6119,13 @@ var ContractOwnershipIndex = class {
5816
6119
  }
5817
6120
  staticString(node, seen) {
5818
6121
  if (!node) return void 0;
5819
- if (ts8.isStringLiteralLike(node)) return node.text;
5820
- if (ts8.isIdentifier(node)) {
6122
+ if (ts9.isStringLiteralLike(node)) return node.text;
6123
+ if (ts9.isIdentifier(node)) {
5821
6124
  const symbol = this.checker.getSymbolAtLocation(node);
5822
6125
  if (!symbol || seen.has(symbol)) return void 0;
5823
6126
  seen.add(symbol);
5824
6127
  for (const declaration of resolvedSymbol(this.checker, symbol).declarations ?? []) {
5825
- if (ts8.isVariableDeclaration(declaration) && declaration.initializer) {
6128
+ if (ts9.isVariableDeclaration(declaration) && declaration.initializer) {
5826
6129
  const value = this.staticString(declaration.initializer, seen);
5827
6130
  if (value !== void 0) return value;
5828
6131
  }
@@ -5840,20 +6143,20 @@ var ContractOwnershipIndex = class {
5840
6143
  this.followSchemaDeclaration(declaration, ownership, seen);
5841
6144
  }
5842
6145
  }
5843
- ts8.forEachChild(node, (child) => {
6146
+ ts9.forEachChild(node, (child) => {
5844
6147
  this.markSchemaExpression(child, ownership, seen);
5845
6148
  });
5846
6149
  }
5847
6150
  schemaReferenceSymbol(node) {
5848
- if (ts8.isIdentifier(node)) {
6151
+ if (ts9.isIdentifier(node)) {
5849
6152
  if (!node.text.endsWith("Schema")) return void 0;
5850
6153
  return this.checker.getSymbolAtLocation(node);
5851
6154
  }
5852
- if (ts8.isPropertyAccessExpression(node)) {
6155
+ if (ts9.isPropertyAccessExpression(node)) {
5853
6156
  if (!node.name.text.endsWith("Schema")) return void 0;
5854
6157
  return this.checker.getSymbolAtLocation(node.name);
5855
6158
  }
5856
- if (ts8.isElementAccessExpression(node) && ts8.isStringLiteralLike(node.argumentExpression)) {
6159
+ if (ts9.isElementAccessExpression(node) && ts9.isStringLiteralLike(node.argumentExpression)) {
5857
6160
  if (!node.argumentExpression.text.endsWith("Schema")) return void 0;
5858
6161
  return this.checker.getSymbolAtLocation(node.argumentExpression);
5859
6162
  }
@@ -5861,15 +6164,15 @@ var ContractOwnershipIndex = class {
5861
6164
  }
5862
6165
  followSchemaDeclaration(declaration, ownership, seen) {
5863
6166
  this.setSchemaOwnership(declaration, ownership);
5864
- if (ts8.isVariableDeclaration(declaration) && declaration.initializer) {
6167
+ if (ts9.isVariableDeclaration(declaration) && declaration.initializer) {
5865
6168
  this.markSchemaExpression(declaration.initializer, ownership, seen);
5866
6169
  return;
5867
6170
  }
5868
- if (ts8.isPropertyAssignment(declaration)) {
6171
+ if (ts9.isPropertyAssignment(declaration)) {
5869
6172
  this.markSchemaExpression(declaration.initializer, ownership, seen);
5870
6173
  return;
5871
6174
  }
5872
- if (ts8.isShorthandPropertyAssignment(declaration)) {
6175
+ if (ts9.isShorthandPropertyAssignment(declaration)) {
5873
6176
  const valueSymbol = this.checker.getShorthandAssignmentValueSymbol(declaration);
5874
6177
  if (!valueSymbol || seen.has(valueSymbol)) return;
5875
6178
  seen.add(valueSymbol);
@@ -5913,7 +6216,7 @@ function contractOwnershipResolver(context) {
5913
6216
  }
5914
6217
 
5915
6218
  // eslint/rules/no-redundant-alias.ts
5916
- 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";
5917
6220
  var VALUE_SENTINELS = /* @__PURE__ */ new Set(["undefined", "NaN", "Infinity"]);
5918
6221
  var HTTP_METHODS = /* @__PURE__ */ new Set(["GET", "POST", "PUT", "PATCH", "DELETE", "HEAD", "OPTIONS"]);
5919
6222
  var FRAMEWORK_MAPPING_KEYS = /* @__PURE__ */ new Set(["default", "apiRoutePath"]);
@@ -5946,14 +6249,14 @@ function aliasedTypeName(annotation) {
5946
6249
  function aliasMessage(alias, source) {
5947
6250
  const aliasName = alias ?? "This declaration";
5948
6251
  const sourceName = source ?? "the original symbol";
5949
- 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}`;
5950
6253
  }
5951
6254
  function bindingAliasMessage(alias, source) {
5952
- 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}`;
5953
6256
  }
5954
- function objectPropertyMessage(propertyName5, source) {
5955
- if (source === propertyName5) return `Use property shorthand for "${propertyName5}". ${DOC5}`;
5956
- 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}`;
5957
6260
  }
5958
6261
  function normalizePropertyName(name) {
5959
6262
  return name.replace(/[-_\s]/g, "").toLowerCase();
@@ -5966,12 +6269,12 @@ function memberPropertyName2(node) {
5966
6269
  }
5967
6270
  return void 0;
5968
6271
  }
5969
- function isNamedMemberValue(propertyName5) {
5970
- return /^[A-Z]/.test(propertyName5);
6272
+ function isNamedMemberValue(propertyName6) {
6273
+ return /^[A-Z]/.test(propertyName6);
5971
6274
  }
5972
- function isQualifiedSourceField(propertyName5, sourceMember, sourcePropertyName) {
6275
+ function isQualifiedSourceField(propertyName6, sourceMember, sourcePropertyName) {
5973
6276
  if (sourceMember.type !== "MemberExpression" || sourceMember.object.type !== "Identifier") return false;
5974
- return normalizePropertyName(propertyName5) === normalizePropertyName(`${sourceMember.object.name}${sourcePropertyName}`);
6277
+ return normalizePropertyName(propertyName6) === normalizePropertyName(`${sourceMember.object.name}${sourcePropertyName}`);
5975
6278
  }
5976
6279
  function isInsideSchemaDeclaration(node) {
5977
6280
  let current = node;
@@ -5983,11 +6286,11 @@ function isInsideSchemaDeclaration(node) {
5983
6286
  }
5984
6287
  return false;
5985
6288
  }
5986
- function semanticMappingMessage(propertyName5, sourcePropertyName) {
5987
- 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}`;
5988
6291
  }
5989
- function unknownContractOwnershipMessage(propertyName5, sourcePropertyName) {
5990
- 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}`;
5991
6294
  }
5992
6295
  function destructuredBindingSource(context, identifier) {
5993
6296
  const initialScope = context.sourceCode.getScope(identifier);
@@ -6014,7 +6317,7 @@ function destructuredBindingSource(context, identifier) {
6014
6317
  }
6015
6318
  return void 0;
6016
6319
  }
6017
- function contractMappingViolation(propertyName5, sourcePropertyName, sourceResolution, targetResolution) {
6320
+ function contractMappingViolation(propertyName6, sourcePropertyName, sourceResolution, targetResolution) {
6018
6321
  if (sourceResolution.kind === "non-contract" || targetResolution.kind === "non-contract") return void 0;
6019
6322
  if ((sourceResolution.ownership === "third-party" || sourceResolution.ownership === "platform") && targetResolution.kind !== "missing") {
6020
6323
  return void 0;
@@ -6025,11 +6328,11 @@ function contractMappingViolation(propertyName5, sourcePropertyName, sourceResol
6025
6328
  const hasDataContract = sourceResolution.kind === "data-contract" || targetResolution.kind === "data-contract";
6026
6329
  if (!hasDataContract) return void 0;
6027
6330
  if (sourceResolution.kind === "missing" || targetResolution.kind === "missing" || sourceResolution.ownership === "unknown" || targetResolution.ownership === "unknown") {
6028
- return unknownContractOwnershipMessage(propertyName5, sourcePropertyName);
6331
+ return unknownContractOwnershipMessage(propertyName6, sourcePropertyName);
6029
6332
  }
6030
6333
  if (sourceResolution.kind !== "data-contract") return void 0;
6031
6334
  if (sourceResolution.ownership !== "first-party" || targetResolution.ownership !== "first-party") return void 0;
6032
- return semanticMappingMessage(propertyName5, sourcePropertyName);
6335
+ return semanticMappingMessage(propertyName6, sourcePropertyName);
6033
6336
  }
6034
6337
  var noRedundantAliasRule = {
6035
6338
  meta: {
@@ -6049,7 +6352,7 @@ var noRedundantAliasRule = {
6049
6352
  if (declaration.type !== "VariableDeclaration" || declaration.kind !== "const") return;
6050
6353
  if (node.init.type === "Identifier") {
6051
6354
  const exported = declaration.parent.type === "ExportNamedDeclaration";
6052
- 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);
6053
6356
  if (frameworkRouteAlias || VALUE_SENTINELS.has(node.init.name)) return;
6054
6357
  context.report({
6055
6358
  node,
@@ -6058,14 +6361,14 @@ var noRedundantAliasRule = {
6058
6361
  return;
6059
6362
  }
6060
6363
  if (node.init.type !== "MemberExpression") return;
6061
- let propertyName5;
6364
+ let propertyName6;
6062
6365
  if (!node.init.computed && node.init.property.type === "Identifier") {
6063
- propertyName5 = node.init.property.name;
6366
+ propertyName6 = node.init.property.name;
6064
6367
  }
6065
6368
  if (node.init.computed && node.init.property.type === "Literal" && typeof node.init.property.value === "string") {
6066
- propertyName5 = node.init.property.value;
6369
+ propertyName6 = node.init.property.value;
6067
6370
  }
6068
- if (propertyName5 === void 0 || propertyName5 === node.id.name) return;
6371
+ if (propertyName6 === void 0 || propertyName6 === node.id.name) return;
6069
6372
  context.report({
6070
6373
  node,
6071
6374
  message: bindingAliasMessage(node.id.name, context.sourceCode.getText(node.init))
@@ -6073,22 +6376,22 @@ var noRedundantAliasRule = {
6073
6376
  },
6074
6377
  Property(node) {
6075
6378
  if (node.computed) return;
6076
- let propertyName5;
6077
- if (node.key.type === "Identifier") propertyName5 = node.key.name;
6379
+ let propertyName6;
6380
+ if (node.key.type === "Identifier") propertyName6 = node.key.name;
6078
6381
  if (node.key.type === "Literal" && typeof node.key.value === "string") {
6079
- propertyName5 = node.key.value;
6382
+ propertyName6 = node.key.value;
6080
6383
  }
6081
- if (propertyName5 === void 0) return;
6384
+ if (propertyName6 === void 0) return;
6082
6385
  if (node.parent.type === "ObjectPattern") {
6083
6386
  let binding;
6084
6387
  if (node.value.type === "Identifier") binding = node.value;
6085
6388
  if (node.value.type === "AssignmentPattern" && node.value.left.type === "Identifier") {
6086
6389
  binding = node.value.left;
6087
6390
  }
6088
- if (!binding || binding.name === propertyName5) return;
6391
+ if (!binding || binding.name === propertyName6) return;
6089
6392
  context.report({
6090
6393
  node,
6091
- message: bindingAliasMessage(binding.name, propertyName5)
6394
+ message: bindingAliasMessage(binding.name, propertyName6)
6092
6395
  });
6093
6396
  return;
6094
6397
  }
@@ -6097,12 +6400,12 @@ var noRedundantAliasRule = {
6097
6400
  if (node.value.type === "Identifier") {
6098
6401
  if (node.shorthand) return;
6099
6402
  const source = node.value.name;
6100
- if (propertyName5 === source) {
6403
+ if (propertyName6 === source) {
6101
6404
  context.report({
6102
6405
  node,
6103
- message: objectPropertyMessage(propertyName5, source),
6406
+ message: objectPropertyMessage(propertyName6, source),
6104
6407
  fix(fixer) {
6105
- return fixer.replaceText(node, propertyName5);
6408
+ return fixer.replaceText(node, propertyName6);
6106
6409
  }
6107
6410
  });
6108
6411
  return;
@@ -6110,29 +6413,29 @@ var noRedundantAliasRule = {
6110
6413
  const bindingSource = destructuredBindingSource(context, node.value);
6111
6414
  if (!bindingSource || !ownershipResolver) return;
6112
6415
  const sourcePropertyName2 = bindingSource.propertyName;
6113
- if (normalizePropertyName(propertyName5) === normalizePropertyName(sourcePropertyName2)) return;
6114
- 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;
6115
6418
  const sourceResolution2 = ownershipResolver.sourceBinding(bindingSource.declarator, sourcePropertyName2);
6116
- const targetResolution2 = ownershipResolver.targetProperty(node, propertyName5);
6419
+ const targetResolution2 = ownershipResolver.targetProperty(node, propertyName6);
6117
6420
  const hasDataContract = sourceResolution2.kind === "data-contract" || targetResolution2.kind === "data-contract";
6118
6421
  if (!hasDataContract) return;
6119
6422
  context.report({
6120
6423
  node,
6121
- message: contractMappingViolation(propertyName5, sourcePropertyName2, sourceResolution2, targetResolution2) ?? objectPropertyMessage(propertyName5, source)
6424
+ message: contractMappingViolation(propertyName6, sourcePropertyName2, sourceResolution2, targetResolution2) ?? objectPropertyMessage(propertyName6, source)
6122
6425
  });
6123
6426
  return;
6124
6427
  }
6125
6428
  if (node.value.type !== "MemberExpression") return;
6126
6429
  const sourcePropertyName = memberPropertyName2(node.value);
6127
6430
  if (sourcePropertyName === void 0) return;
6128
- if (normalizePropertyName(propertyName5) === normalizePropertyName(sourcePropertyName)) return;
6129
- if (FRAMEWORK_MAPPING_KEYS.has(propertyName5) || isNamedMemberValue(sourcePropertyName)) return;
6130
- 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;
6131
6434
  if (!ownershipResolver) return;
6132
6435
  const sourceResolution = ownershipResolver.sourceMember(node.value);
6133
- const targetResolution = ownershipResolver.targetProperty(node, propertyName5);
6436
+ const targetResolution = ownershipResolver.targetProperty(node, propertyName6);
6134
6437
  const violation = contractMappingViolation(
6135
- propertyName5,
6438
+ propertyName6,
6136
6439
  sourcePropertyName,
6137
6440
  sourceResolution,
6138
6441
  targetResolution
@@ -6156,6 +6459,11 @@ var noRedundantAliasRule = {
6156
6459
  },
6157
6460
  ImportSpecifier(node) {
6158
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
+ }
6159
6467
  context.report({
6160
6468
  node,
6161
6469
  message: bindingAliasMessage(node.local.name, node.imported.name)
@@ -6167,7 +6475,7 @@ var noRedundantAliasRule = {
6167
6475
  const source = specifier.local.name;
6168
6476
  const alias = specifier.exported.name;
6169
6477
  if (source === alias) continue;
6170
- 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);
6171
6479
  if (frameworkRouteAlias) continue;
6172
6480
  context.report({
6173
6481
  node: specifier,
@@ -6192,7 +6500,7 @@ var noRedundantAliasRule = {
6192
6500
  };
6193
6501
 
6194
6502
  // eslint/rules/no-util-barrel.ts
6195
- import path44 from "path";
6503
+ import path45 from "path";
6196
6504
  var noUtilBarrelRule = {
6197
6505
  meta: {
6198
6506
  schema: [],
@@ -6202,7 +6510,7 @@ var noUtilBarrelRule = {
6202
6510
  }
6203
6511
  },
6204
6512
  create(context) {
6205
- const filename = path44.resolve(context.filename);
6513
+ const filename = path45.resolve(context.filename);
6206
6514
  const sourceRoot = sourceRootOf3(context, filename);
6207
6515
  return {
6208
6516
  Program(node) {
@@ -6211,7 +6519,7 @@ var noUtilBarrelRule = {
6211
6519
  if (!target) continue;
6212
6520
  const segments = target.replace(/\\/g, "/").split("/");
6213
6521
  const utilsIndex = segments.lastIndexOf("utils");
6214
- if (utilsIndex < 0 || !path44.basename(target).startsWith("index.")) continue;
6522
+ if (utilsIndex < 0 || !path45.basename(target).startsWith("index.")) continue;
6215
6523
  context.report({
6216
6524
  node,
6217
6525
  message: `Import utilities directly instead of through "${specifier}". See docs/next-codebase-guide/rules/utilities-rule.md`
@@ -6231,16 +6539,146 @@ function importSpecifiers2(source) {
6231
6539
  return specifiers;
6232
6540
  }
6233
6541
  function sourceRootOf3(context, filename) {
6234
- const marker = `${path44.sep}src${path44.sep}`;
6542
+ const marker = `${path45.sep}src${path45.sep}`;
6235
6543
  const srcIndex = filename.lastIndexOf(marker);
6236
6544
  if (srcIndex >= 0) return filename.slice(0, srcIndex + marker.length - 1);
6237
- return path44.resolve(context.cwd ?? process.cwd(), "src");
6545
+ return path45.resolve(context.cwd ?? process.cwd(), "src");
6238
6546
  }
6239
6547
 
6240
- // 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
+ }
6241
6555
  function memberName2(member) {
6242
6556
  return member.name.type === "String" ? member.name.value : member.name.name;
6243
6557
  }
6558
+ function scriptsOf(root) {
6559
+ if (root.type !== "Object") return /* @__PURE__ */ new Map();
6560
+ const scripts = root.members.find((member) => memberName2(member) === "scripts");
6561
+ const members = scripts?.value.type === "Object" ? scripts.value.members : [];
6562
+ return new Map(
6563
+ members.flatMap(
6564
+ (member) => member.value.type === "String" ? [[memberName2(member), member.value.value]] : []
6565
+ )
6566
+ );
6567
+ }
6568
+ function events(workflow) {
6569
+ const on = workflow.on;
6570
+ if (typeof on === "string") return { [on]: null };
6571
+ if (Array.isArray(on)) {
6572
+ return Object.fromEntries(
6573
+ on.filter((item) => typeof item === "string").map((item) => [item, null])
6574
+ );
6575
+ }
6576
+ return mapping(on) ?? {};
6577
+ }
6578
+ function branchesTrigger(workflow) {
6579
+ const push = events(workflow).push;
6580
+ const branches = mapping(push)?.branches;
6581
+ return typeof branches === "string" ? branches.length > 0 : Array.isArray(branches) && branches.some((branch) => typeof branch === "string" && branch.length > 0);
6582
+ }
6583
+ function jobs(workflow) {
6584
+ return mapping(workflow.jobs) ?? {};
6585
+ }
6586
+ function steps(job) {
6587
+ const entries = mapping(job)?.steps;
6588
+ return Array.isArray(entries) ? entries.flatMap((entry) => {
6589
+ const step = mapping(entry);
6590
+ return step ? [step] : [];
6591
+ }) : [];
6592
+ }
6593
+ function runsScript(run, name) {
6594
+ if (typeof run !== "string") return false;
6595
+ return new RegExp(`(?:^|[\\n;&|])\\s*npm\\s+run\\s+${name}(?=\\s|$)`).test(run);
6596
+ }
6597
+ function runsNpmCi(run) {
6598
+ return typeof run === "string" && /(?:^|[\n;&|])\s*npm\s+ci(?=\s|$)/.test(run);
6599
+ }
6600
+ function usesAction(value, action) {
6601
+ return typeof value === "string" && value.startsWith(`${action}@`);
6602
+ }
6603
+ function readWorkflows(dir) {
6604
+ const workflows = [];
6605
+ const errors = [];
6606
+ for (const file of readdirSync4(dir).filter((name) => /\.ya?ml$/i.test(name)).sort()) {
6607
+ try {
6608
+ const parsed = parse2(readFileSync11(path46.join(dir, file), "utf8"), { uniqueKeys: true });
6609
+ const content = mapping(parsed);
6610
+ if (!content) throw new Error("expected a YAML mapping");
6611
+ workflows.push(content);
6612
+ } catch (error) {
6613
+ errors.push(`${file}: ${error instanceof Error ? error.message : String(error)}`);
6614
+ }
6615
+ }
6616
+ return { workflows, errors };
6617
+ }
6618
+ var ciChecksRule = {
6619
+ meta: {
6620
+ schema: [],
6621
+ type: "problem",
6622
+ docs: {
6623
+ description: "Require GitHub Actions validation for pull requests and branch pushes."
6624
+ }
6625
+ },
6626
+ create(context) {
6627
+ return {
6628
+ Document(node) {
6629
+ if (!context.filename.endsWith("package.json")) return;
6630
+ const dir = path46.join(context.cwd, ".github", "workflows");
6631
+ if (!existsSync6(dir)) return;
6632
+ const report3 = (message) => {
6633
+ context.report({ node, message });
6634
+ };
6635
+ const { workflows, errors } = readWorkflows(dir);
6636
+ for (const error of errors) report3(`Invalid GitHub Actions workflow: ${error}`);
6637
+ const check = workflows.find(
6638
+ (workflow) => Object.hasOwn(events(workflow), "pull_request") && branchesTrigger(workflow)
6639
+ );
6640
+ if (!check) {
6641
+ report3("GitHub Actions must run shared checks for pull requests and branch pushes.");
6642
+ return;
6643
+ }
6644
+ const scripts = scriptsOf(node.body);
6645
+ const requiredScripts = ["format", "lint", "typecheck", "test:unit:coverage:check"];
6646
+ if (scripts.has("build")) requiredScripts.push("build");
6647
+ const checkJobs = Object.values(jobs(check));
6648
+ const allSteps = checkJobs.flatMap(steps);
6649
+ for (const job of checkJobs) {
6650
+ const jobSteps = steps(job);
6651
+ const firstCheck = jobSteps.findIndex((step) => requiredScripts.some((name) => runsScript(step.run, name)));
6652
+ if (firstCheck < 0) continue;
6653
+ const checkout = jobSteps.findIndex((step) => usesAction(step.uses, "actions/checkout"));
6654
+ const install = jobSteps.findIndex((step) => runsNpmCi(step.run));
6655
+ if (checkout < 0 || checkout >= firstCheck) {
6656
+ report3("GitHub Actions checks must check out the repository before running npm scripts.");
6657
+ }
6658
+ if (install < 0 || install >= firstCheck || checkout >= 0 && install <= checkout) {
6659
+ report3("GitHub Actions checks must install dependencies with npm ci.");
6660
+ }
6661
+ }
6662
+ for (const name of requiredScripts) {
6663
+ if (!allSteps.some((step) => runsScript(step.run, name))) {
6664
+ report3(`GitHub Actions checks must run npm run ${name}.`);
6665
+ }
6666
+ }
6667
+ const coverage = scripts.get("test:unit:coverage:check");
6668
+ if (!coverage || !/npm\s+run\s+test:unit:coverage(?=\s|$)/.test(coverage) || !coverage.includes("--coverage.thresholds.autoUpdate=false") || !/&&\s*git\s+diff\s+--exit-code/.test(coverage)) {
6669
+ report3(
6670
+ "package.json must declare test:unit:coverage:check that runs coverage with autoUpdate=false and verifies no Git diff."
6671
+ );
6672
+ }
6673
+ }
6674
+ };
6675
+ }
6676
+ };
6677
+
6678
+ // eslint/rules/package-json/exact-version.ts
6679
+ function memberName3(member) {
6680
+ return member.name.type === "String" ? member.name.value : member.name.name;
6681
+ }
6244
6682
  var EXACT_VERSION_PATTERN = /^\d+\.\d+\.\d+$/;
6245
6683
  function memberValue(member) {
6246
6684
  return member.value.type === "String" ? member.value.value : null;
@@ -6259,7 +6697,7 @@ var exactVersionRule = {
6259
6697
  const root = node.body;
6260
6698
  if (root.type !== "Object") return;
6261
6699
  for (const key of ["dependencies", "devDependencies"]) {
6262
- const section = root.members.find((member) => memberName2(member) === key);
6700
+ const section = root.members.find((member) => memberName3(member) === key);
6263
6701
  if (section?.value.type !== "Object") continue;
6264
6702
  for (const member of section.value.members) {
6265
6703
  const version = memberValue(member);
@@ -6267,7 +6705,7 @@ var exactVersionRule = {
6267
6705
  if (!EXACT_VERSION_PATTERN.test(version)) {
6268
6706
  context.report({
6269
6707
  node: member,
6270
- message: `${memberName2(member)} must pin an exact version (e.g. "1.2.3"), not a range or cap such as "${version}".`
6708
+ message: `${memberName3(member)} must pin an exact version (e.g. "1.2.3"), not a range or cap such as "${version}".`
6271
6709
  });
6272
6710
  }
6273
6711
  }
@@ -6278,7 +6716,7 @@ var exactVersionRule = {
6278
6716
  };
6279
6717
 
6280
6718
  // eslint/rules/package-json/lint-setup.ts
6281
- function memberName3(member) {
6719
+ function memberName4(member) {
6282
6720
  return member.name.type === "String" ? member.name.value : member.name.name;
6283
6721
  }
6284
6722
  function memberValue2(member) {
@@ -6320,9 +6758,9 @@ var lintSetupRule = {
6320
6758
  Document(node) {
6321
6759
  const root = node.body;
6322
6760
  if (root.type !== "Object") return;
6323
- const scripts = root.members.find((member) => memberName3(member) === "scripts");
6761
+ const scripts = root.members.find((member) => memberName4(member) === "scripts");
6324
6762
  const scriptMembers = scripts?.value.type === "Object" ? scripts.value.members : [];
6325
- const findScript = (name) => scriptMembers.find((member) => memberName3(member) === name);
6763
+ const findScript = (name) => scriptMembers.find((member) => memberName4(member) === name);
6326
6764
  const lint = findScript("lint");
6327
6765
  const lintCommand = memberValue2(lint);
6328
6766
  if (lintCommand === void 0 || !runsEslintDirectly(lintCommand) || !REPOSITORY_ARGUMENT_PATTERN.test(lintCommand)) {
@@ -6355,10 +6793,10 @@ var lintSetupRule = {
6355
6793
  message: 'package.json must declare a "format:staged" script that runs prettier with no repository-wide argument (e.g. "prettier --write").'
6356
6794
  });
6357
6795
  }
6358
- const lintStagedConfig = root.members.find((member) => memberName3(member) === "lint-staged");
6796
+ const lintStagedConfig = root.members.find((member) => memberName4(member) === "lint-staged");
6359
6797
  const stagedMembers = lintStagedConfig?.value.type === "Object" ? lintStagedConfig.value.members : [];
6360
6798
  const runsStagedScriptForGlob = (name, matchesGlob) => stagedMembers.some(
6361
- (member) => matchesGlob(memberName3(member)) && stringValues(member.value).some((command) => runsNamedScript(command, name))
6799
+ (member) => matchesGlob(memberName4(member)) && stringValues(member.value).some((command) => runsNamedScript(command, name))
6362
6800
  );
6363
6801
  const runsStagedScriptForExtension = (name, extension) => runsStagedScriptForGlob(name, (glob) => globIncludesExtension(glob, extension));
6364
6802
  const hasStagedSourceLint = runsStagedScriptForGlob("lint:staged", (glob) => SOURCE_GLOB_PATTERN.test(glob));
@@ -6409,13 +6847,13 @@ var NEXTJS_STACK_DEV_DEPENDENCIES = [
6409
6847
  "@testing-library/react",
6410
6848
  "@testing-library/dom"
6411
6849
  ];
6412
- function memberName4(member) {
6850
+ function memberName5(member) {
6413
6851
  return member.name.type === "String" ? member.name.value : member.name.name;
6414
6852
  }
6415
6853
  function sectionPackages(root, section) {
6416
- const member = root.type === "Object" ? root.members.find((entry) => memberName4(entry) === section) : void 0;
6854
+ const member = root.type === "Object" ? root.members.find((entry) => memberName5(entry) === section) : void 0;
6417
6855
  if (member?.value.type !== "Object") return /* @__PURE__ */ new Set();
6418
- return new Set(member.value.members.map(memberName4));
6856
+ return new Set(member.value.members.map(memberName5));
6419
6857
  }
6420
6858
  var nextjsStackRule = {
6421
6859
  meta: {
@@ -6452,9 +6890,9 @@ var nextjsStackRule = {
6452
6890
  };
6453
6891
 
6454
6892
  // eslint/rules/package-json/vitest-coverage.ts
6455
- import { existsSync as existsSync5, readFileSync as readFileSync10 } from "fs";
6456
- import path45 from "path";
6457
- function memberName5(member) {
6893
+ import { existsSync as existsSync7, readFileSync as readFileSync12 } from "fs";
6894
+ import path47 from "path";
6895
+ function memberName6(member) {
6458
6896
  return member.name.type === "String" ? member.name.value : member.name.name;
6459
6897
  }
6460
6898
  function memberValue3(member) {
@@ -6492,9 +6930,9 @@ var vitestCoverageRule = {
6492
6930
  Document(node) {
6493
6931
  const root = node.body;
6494
6932
  if (root.type !== "Object") return;
6495
- const devDependencies = root.members.find((member) => memberName5(member) === "devDependencies");
6933
+ const devDependencies = root.members.find((member) => memberName6(member) === "devDependencies");
6496
6934
  const devDependencyNames = new Set(
6497
- devDependencies?.value.type === "Object" ? devDependencies.value.members.map(memberName5) : []
6935
+ devDependencies?.value.type === "Object" ? devDependencies.value.members.map(memberName6) : []
6498
6936
  );
6499
6937
  if (!devDependencyNames.has("vitest")) {
6500
6938
  context.report({ node, message: "vitest must be listed in package.json as a devDependency." });
@@ -6505,9 +6943,9 @@ var vitestCoverageRule = {
6505
6943
  message: "@vitest/coverage-v8 must be listed in package.json as a devDependency."
6506
6944
  });
6507
6945
  }
6508
- const scripts = root.members.find((member) => memberName5(member) === "scripts");
6946
+ const scripts = root.members.find((member) => memberName6(member) === "scripts");
6509
6947
  const scriptMembers = scripts?.value.type === "Object" ? scripts.value.members : [];
6510
- const unit = scriptMembers.find((member) => memberName5(member) === "test:unit");
6948
+ const unit = scriptMembers.find((member) => memberName6(member) === "test:unit");
6511
6949
  const unitCommand = memberValue3(unit);
6512
6950
  if (unitCommand === void 0 || !/\bvitest\b/.test(unitCommand) || COVERAGE_FLAG_PATTERN.test(unitCommand)) {
6513
6951
  context.report({
@@ -6515,7 +6953,7 @@ var vitestCoverageRule = {
6515
6953
  message: 'package.json must declare a "test:unit" script that runs Vitest without coverage.'
6516
6954
  });
6517
6955
  }
6518
- const coverage = scriptMembers.find((member) => memberName5(member) === "test:unit:coverage");
6956
+ const coverage = scriptMembers.find((member) => memberName6(member) === "test:unit:coverage");
6519
6957
  const coverageCommand = memberValue3(coverage);
6520
6958
  if (coverageCommand === void 0 || !/\bvitest\b/.test(coverageCommand) || !COVERAGE_FLAG_PATTERN.test(coverageCommand)) {
6521
6959
  context.report({
@@ -6523,7 +6961,7 @@ var vitestCoverageRule = {
6523
6961
  message: 'package.json must declare a "test:unit:coverage" script that runs Vitest with coverage.'
6524
6962
  });
6525
6963
  }
6526
- const configName = VITEST_CONFIG_NAMES.find((name) => existsSync5(path45.join(context.cwd, name)));
6964
+ const configName = VITEST_CONFIG_NAMES.find((name) => existsSync7(path47.join(context.cwd, name)));
6527
6965
  if (!configName) {
6528
6966
  context.report({
6529
6967
  node,
@@ -6531,7 +6969,7 @@ var vitestCoverageRule = {
6531
6969
  });
6532
6970
  return;
6533
6971
  }
6534
- const content = readFileSync10(path45.join(context.cwd, configName), "utf8");
6972
+ const content = readFileSync12(path47.join(context.cwd, configName), "utf8");
6535
6973
  for (const metric of THRESHOLD_METRICS) {
6536
6974
  if (!new RegExp(`\\b${metric}\\s*:\\s*[1-9]\\d*`).test(content)) {
6537
6975
  context.report({ node, message: `${configName} must set a coverage threshold above zero for ${metric}.` });
@@ -6543,7 +6981,7 @@ var vitestCoverageRule = {
6543
6981
  message: `${configName} must enable coverage.thresholds.autoUpdate with true or the monotonic 0.1-point buffered formatter.`
6544
6982
  });
6545
6983
  }
6546
- const stagedTests = scriptMembers.find((member) => memberName5(member) === "test:unit:staged");
6984
+ const stagedTests = scriptMembers.find((member) => memberName6(member) === "test:unit:staged");
6547
6985
  const stagedTestsCommand = memberValue3(stagedTests);
6548
6986
  if (stagedTestsCommand === void 0 || !/\bvitest\b/.test(stagedTestsCommand) || !RELATED_PATTERN.test(stagedTestsCommand) || COVERAGE_FLAG_PATTERN.test(stagedTestsCommand)) {
6549
6987
  context.report({
@@ -6551,9 +6989,9 @@ var vitestCoverageRule = {
6551
6989
  message: 'package.json must declare a "test:unit:staged" script that runs vitest related without coverage.'
6552
6990
  });
6553
6991
  }
6554
- const lintStaged = root.members.find((member) => memberName5(member) === "lint-staged");
6992
+ const lintStaged = root.members.find((member) => memberName6(member) === "lint-staged");
6555
6993
  const hasStagedTests = lintStaged?.value.type === "Object" && lintStaged.value.members.some(
6556
- (member) => SOURCE_GLOB_PATTERN2.test(memberName5(member)) && stringValues2(member.value).some((command) => command.includes("npm run test:unit:staged"))
6994
+ (member) => SOURCE_GLOB_PATTERN2.test(memberName6(member)) && stringValues2(member.value).some((command) => command.includes("npm run test:unit:staged"))
6557
6995
  );
6558
6996
  if (!hasStagedTests) {
6559
6997
  context.report({
@@ -6568,6 +7006,7 @@ var vitestCoverageRule = {
6568
7006
 
6569
7007
  // eslint/rules/package-json/index.ts
6570
7008
  var repoPackageJsonRules = {
7009
+ "ci-checks": ciChecksRule,
6571
7010
  "exact-version": exactVersionRule,
6572
7011
  "lint-setup": lintSetupRule,
6573
7012
  "vitest-coverage": vitestCoverageRule
@@ -6577,8 +7016,8 @@ var nextjsPackageJsonRules = {
6577
7016
  };
6578
7017
 
6579
7018
  // eslint/rules/prefer-enum.ts
6580
- import path46 from "path";
6581
- import ts9 from "typescript";
7019
+ import path48 from "path";
7020
+ import ts10 from "typescript";
6582
7021
  function isConstAssertion(node) {
6583
7022
  const typeAnnotation = node.typeAnnotation;
6584
7023
  return typeAnnotation?.type === "TSTypeReference" && typeAnnotation.typeName?.type === "Identifier" && typeAnnotation.typeName.name === "const";
@@ -6600,7 +7039,7 @@ function isZodCall(node, method) {
6600
7039
  const { callee } = node;
6601
7040
  return callee?.type === "MemberExpression" && !callee.computed && callee.object.type === "Identifier" && callee.object.name === "z" && callee.property.type === "Identifier" && callee.property.name === method;
6602
7041
  }
6603
- function propertyName4(property) {
7042
+ function propertyName5(property) {
6604
7043
  if (property.computed) return void 0;
6605
7044
  if (property.key.type === "Identifier") return property.key.name;
6606
7045
  if (property.key.type === "Literal" && typeof property.key.value === "string") return property.key.value;
@@ -6611,7 +7050,7 @@ function rawZodDiscriminantLiteral(schemaCall, discriminator) {
6611
7050
  const shape = schemaCall.arguments[0];
6612
7051
  if (shape?.type !== "ObjectExpression") return void 0;
6613
7052
  for (const property of shape.properties) {
6614
- if (property.type !== "Property" || propertyName4(property) !== discriminator) continue;
7053
+ if (property.type !== "Property" || propertyName5(property) !== discriminator) continue;
6615
7054
  if (property.value.type !== "CallExpression" || !isZodCall(property.value, "literal")) return void 0;
6616
7055
  const literal = property.value.arguments[0];
6617
7056
  if (literal?.type === "Literal" && (typeof literal.value === "string" || typeof literal.value === "number")) {
@@ -6632,13 +7071,13 @@ function isLiteralTupleAssertion(node) {
6632
7071
  return values.every((value) => value !== void 0) && new Set(values).size >= 2;
6633
7072
  }
6634
7073
  function isTsLiteralTupleDeclaration(declaration) {
6635
- if (!ts9.isVariableDeclaration(declaration) || !declaration.initializer) return false;
7074
+ if (!ts10.isVariableDeclaration(declaration) || !declaration.initializer) return false;
6636
7075
  const init = declaration.initializer;
6637
- if (!ts9.isAsExpression(init) || !ts9.isTypeReferenceNode(init.type) || !ts9.isIdentifier(init.type.typeName) || init.type.typeName.text !== "const" || !ts9.isArrayLiteralExpression(init.expression) || init.expression.elements.length < 2) {
7076
+ if (!ts10.isAsExpression(init) || !ts10.isTypeReferenceNode(init.type) || !ts10.isIdentifier(init.type.typeName) || init.type.typeName.text !== "const" || !ts10.isArrayLiteralExpression(init.expression) || init.expression.elements.length < 2) {
6638
7077
  return false;
6639
7078
  }
6640
7079
  const values = init.expression.elements.map(
6641
- (element) => ts9.isStringLiteral(element) || ts9.isNumericLiteral(element) ? element.text : void 0
7080
+ (element) => ts10.isStringLiteral(element) || ts10.isNumericLiteral(element) ? element.text : void 0
6642
7081
  );
6643
7082
  return values.every((value) => value !== void 0) && new Set(values).size >= 2;
6644
7083
  }
@@ -6651,9 +7090,9 @@ var preferEnumRule = {
6651
7090
  }
6652
7091
  },
6653
7092
  create(context) {
6654
- const filename = path46.resolve(context.filename);
7093
+ const filename = path48.resolve(context.filename);
6655
7094
  const sourceRoot = sourceRootOf(context);
6656
- if (!filename.startsWith(sourceRoot + path46.sep)) return {};
7095
+ if (!filename.startsWith(sourceRoot + path48.sep)) return {};
6657
7096
  const objectSchemas = /* @__PURE__ */ new Map();
6658
7097
  const literalTuples = /* @__PURE__ */ new Set();
6659
7098
  const enumTupleUses = [];
@@ -6667,7 +7106,7 @@ var preferEnumRule = {
6667
7106
  const checker = services.program.getTypeChecker();
6668
7107
  const symbol = checker.getSymbolAtLocation(tsNode);
6669
7108
  if (!symbol) return false;
6670
- const original = symbol.flags === ts9.SymbolFlags.Alias ? checker.getAliasedSymbol(symbol) : symbol;
7109
+ const original = symbol.flags === ts10.SymbolFlags.Alias ? checker.getAliasedSymbol(symbol) : symbol;
6671
7110
  return (original.declarations ?? []).some(isTsLiteralTupleDeclaration);
6672
7111
  }
6673
7112
  return {
@@ -6762,8 +7201,8 @@ var preferEnumRule = {
6762
7201
  };
6763
7202
 
6764
7203
  // eslint/rules/prefer-object-destructuring.ts
6765
- import ts10 from "typescript";
6766
- var DOC6 = "See docs/next-codebase-guide/rules/redundant-aliases-rule.md";
7204
+ import ts11 from "typescript";
7205
+ var DOC7 = "See docs/next-codebase-guide/rules/redundant-aliases-rule.md";
6767
7206
  function hasTypeAnnotation(identifier) {
6768
7207
  return "typeAnnotation" in identifier && identifier.typeAnnotation !== void 0;
6769
7208
  }
@@ -6775,19 +7214,19 @@ function directPropertyBinding(context, declarator, isEnumValue) {
6775
7214
  if (member.computed || member.optional || member.property.type !== "Identifier") return void 0;
6776
7215
  if (!memberCanBecomeLocal(member)) return void 0;
6777
7216
  if (context.sourceCode.getCommentsInside(declarator).length > 0) return void 0;
6778
- const propertyName5 = member.property.name;
7217
+ const propertyName6 = member.property.name;
6779
7218
  const localName = declarator.id.name;
6780
- if (propertyName5 !== localName) return void 0;
7219
+ if (propertyName6 !== localName) return void 0;
6781
7220
  const source = member.object;
6782
7221
  const sourceText = context.sourceCode.getText(source);
6783
7222
  return {
6784
7223
  declarator,
6785
7224
  member,
6786
- propertyName: propertyName5,
7225
+ propertyName: propertyName6,
6787
7226
  localName,
6788
7227
  source,
6789
7228
  sourceText,
6790
- bindingText: propertyName5
7229
+ bindingText: propertyName6
6791
7230
  };
6792
7231
  }
6793
7232
  function canGroupSource(source) {
@@ -6805,8 +7244,8 @@ function rootIdentifierName(node) {
6805
7244
  if (node.type !== "MemberExpression" || node.object.type === "Super") return void 0;
6806
7245
  return rootIdentifierName(node.object);
6807
7246
  }
6808
- function isCompliantLocalName(propertyName5) {
6809
- return !propertyName5.includes("_") || /^[A-Z][A-Z0-9]*(?:_[A-Z0-9]+)*$/u.test(propertyName5);
7247
+ function isCompliantLocalName(propertyName6) {
7248
+ return !propertyName6.includes("_") || /^[A-Z][A-Z0-9]*(?:_[A-Z0-9]+)*$/u.test(propertyName6);
6810
7249
  }
6811
7250
  function propertyNameOf(node) {
6812
7251
  if (node.type !== "Property" || node.computed) return void 0;
@@ -6855,8 +7294,8 @@ function enumValueResolver(context) {
6855
7294
  const checker = services.program.getTypeChecker();
6856
7295
  const { esTreeNodeToTSNodeMap: nodeMap } = services;
6857
7296
  const isEnumSymbol = (symbol) => {
6858
- const resolved = symbol.flags === ts10.SymbolFlags.Alias ? checker.getAliasedSymbol(symbol) : symbol;
6859
- return (resolved.declarations ?? []).some((declaration) => ts10.isEnumDeclaration(declaration));
7297
+ const resolved = symbol.flags === ts11.SymbolFlags.Alias ? checker.getAliasedSymbol(symbol) : symbol;
7298
+ return (resolved.declarations ?? []).some((declaration) => ts11.isEnumDeclaration(declaration));
6860
7299
  };
6861
7300
  return (node) => {
6862
7301
  const tsNode = nodeMap.get(node);
@@ -6872,27 +7311,27 @@ function detachableCallResolver(context) {
6872
7311
  if (!services) return () => false;
6873
7312
  const checker = services.program.getTypeChecker();
6874
7313
  const { esTreeNodeToTSNodeMap: nodeMap } = services;
6875
- const isUnboundFunctionType = (type) => ts10.isFunctionTypeNode(type) && !type.parameters.some((parameter) => ts10.isIdentifier(parameter.name) && parameter.name.text === "this");
7314
+ const isUnboundFunctionType = (type) => ts11.isFunctionTypeNode(type) && !type.parameters.some((parameter) => ts11.isIdentifier(parameter.name) && parameter.name.text === "this");
6876
7315
  return (member) => {
6877
7316
  const node = nodeMap.get(member);
6878
- if (!node || !ts10.isPropertyAccessExpression(node)) return false;
7317
+ if (!node || !ts11.isPropertyAccessExpression(node)) return false;
6879
7318
  const symbol = checker.getSymbolAtLocation(node.name);
6880
7319
  const declarations = symbol?.declarations;
6881
7320
  if (!declarations?.length) return false;
6882
7321
  return declarations.every((declaration) => {
6883
- if (ts10.isPropertySignature(declaration) || ts10.isPropertyDeclaration(declaration)) {
6884
- return declaration.type !== void 0 && isUnboundFunctionType(declaration.type) || ts10.isPropertyDeclaration(declaration) && declaration.initializer !== void 0 && ts10.isArrowFunction(declaration.initializer);
7322
+ if (ts11.isPropertySignature(declaration) || ts11.isPropertyDeclaration(declaration)) {
7323
+ return declaration.type !== void 0 && isUnboundFunctionType(declaration.type) || ts11.isPropertyDeclaration(declaration) && declaration.initializer !== void 0 && ts11.isArrowFunction(declaration.initializer);
6885
7324
  }
6886
- if (ts10.isPropertyAssignment(declaration)) return ts10.isArrowFunction(declaration.initializer);
7325
+ if (ts11.isPropertyAssignment(declaration)) return ts11.isArrowFunction(declaration.initializer);
6887
7326
  return false;
6888
7327
  });
6889
7328
  };
6890
7329
  }
6891
7330
  function directMappingRequiresQualifiedAccess(context, ownershipResolver, member) {
6892
- const mapping = renamedDirectMapping(context, member);
6893
- if (!mapping || !ownershipResolver) return false;
6894
- const sourceResolution = ownershipResolver.sourceMember(mapping.sourceMember);
6895
- const targetResolution = ownershipResolver.targetProperty(mapping.property, mapping.targetName);
7331
+ const mapping2 = renamedDirectMapping(context, member);
7332
+ if (!mapping2 || !ownershipResolver) return false;
7333
+ const sourceResolution = ownershipResolver.sourceMember(mapping2.sourceMember);
7334
+ const targetResolution = ownershipResolver.targetProperty(mapping2.property, mapping2.targetName);
6896
7335
  return sourceResolution.kind === "data-contract" || targetResolution.kind === "data-contract";
6897
7336
  }
6898
7337
  function memberCanBeDestructured(context, ownershipResolver, member, isEnumValue) {
@@ -6928,10 +7367,10 @@ function recordMemberUsage(context, scope, ownershipResolver, member, isEnumValu
6928
7367
  if (!isGroupedUsageSource(member.object) || !memberIsRead(context, member, detachableCall)) return;
6929
7368
  const sourceText = context.sourceCode.getText(member.object);
6930
7369
  const usage = objectUsage(scope, sourceText);
6931
- const propertyName5 = member.property.name;
6932
- usage.propertyNames.add(propertyName5);
7370
+ const propertyName6 = member.property.name;
7371
+ usage.propertyNames.add(propertyName6);
6933
7372
  if (!memberIsDirectVariableInitializer(context, member)) {
6934
- usage.directMembers.push({ member, propertyName: propertyName5 });
7373
+ usage.directMembers.push({ member, propertyName: propertyName6 });
6935
7374
  }
6936
7375
  }
6937
7376
  function recordDestructuringUsage(context, scope, declaration, isEnumValue) {
@@ -6954,7 +7393,7 @@ function recordDestructuringUsage(context, scope, declaration, isEnumValue) {
6954
7393
  }
6955
7394
  function scopeUsageMessage(sourceText, propertyNames) {
6956
7395
  const names = [...propertyNames].map((name) => `"${name}"`).join(", ");
6957
- return `${names} are read from "${sourceText}" in the same block. Destructure them together in one declaration. ${DOC6}`;
7396
+ return `${names} are read from "${sourceText}" in the same block. Destructure them together in one declaration. ${DOC7}`;
6958
7397
  }
6959
7398
  function hasBinding(context, node, name) {
6960
7399
  const initialScope = context.sourceCode.getScope(node);
@@ -7058,13 +7497,13 @@ function groupedDestructuringSelections(context, first, isEnumValue) {
7058
7497
  if (!previous || nextNode?.type !== "VariableDeclaration" || nextNode.kind !== first.declaration.kind) break;
7059
7498
  const next = destructuringSelection(context, nextNode, isEnumValue);
7060
7499
  if (next?.sourceText !== first.sourceText) break;
7061
- if (next.propertyNames.some((propertyName5) => seenProperties.has(propertyName5))) break;
7500
+ if (next.propertyNames.some((propertyName6) => seenProperties.has(propertyName6))) break;
7062
7501
  const [, previousEnd] = context.sourceCode.getRange(previous);
7063
7502
  const [nextStart] = context.sourceCode.getRange(nextNode);
7064
7503
  const gap = context.sourceCode.text.slice(previousEnd, nextStart);
7065
7504
  if (!whitespaceKeepsStatementsAdjacent(gap)) break;
7066
7505
  group.push(next);
7067
- for (const propertyName5 of next.propertyNames) seenProperties.add(propertyName5);
7506
+ for (const propertyName6 of next.propertyNames) seenProperties.add(propertyName6);
7068
7507
  }
7069
7508
  return group;
7070
7509
  }
@@ -7072,19 +7511,19 @@ function declarationTerminator(context, declaration) {
7072
7511
  return context.sourceCode.getText(declaration).trimEnd().endsWith(";") ? ";" : "";
7073
7512
  }
7074
7513
  function singlePropertyMessage(binding) {
7075
- return `"${binding.propertyName}" is the only property bound from "${binding.sourceText}". Read "${binding.sourceText}.${binding.propertyName}" directly instead of creating a local binding. ${DOC6}`;
7514
+ return `"${binding.propertyName}" is the only property bound from "${binding.sourceText}". Read "${binding.sourceText}.${binding.propertyName}" directly instead of creating a local binding. ${DOC7}`;
7076
7515
  }
7077
7516
  function groupMessage(bindings) {
7078
7517
  const firstBinding = bindings[0];
7079
- if (!firstBinding) return `Use one object destructuring declaration. ${DOC6}`;
7518
+ if (!firstBinding) return `Use one object destructuring declaration. ${DOC7}`;
7080
7519
  const names = bindings.map(({ localName }) => `"${localName}"`).join(", ");
7081
- return `${names} are derived directly from properties of "${firstBinding.sourceText}". Use one object destructuring declaration. ${DOC6}`;
7520
+ return `${names} are derived directly from properties of "${firstBinding.sourceText}". Use one object destructuring declaration. ${DOC7}`;
7082
7521
  }
7083
7522
  function repeatedDestructuringMessage(group) {
7084
7523
  const first = group[0];
7085
- if (!first) return `Combine repeated destructuring into one declaration. ${DOC6}`;
7524
+ if (!first) return `Combine repeated destructuring into one declaration. ${DOC7}`;
7086
7525
  const names = group.flatMap(({ localNames }) => localNames).map((name) => `"${name}"`).join(", ");
7087
- return `${names} destructure the same source "${first.sourceText}" repeatedly. Combine them into one object destructuring declaration. ${DOC6}`;
7526
+ return `${names} destructure the same source "${first.sourceText}" repeatedly. Combine them into one object destructuring declaration. ${DOC7}`;
7088
7527
  }
7089
7528
  var preferObjectDestructuringRule = {
7090
7529
  meta: {
@@ -7118,9 +7557,9 @@ var preferObjectDestructuringRule = {
7118
7557
  const { member: firstDirectMember } = firstDirectUsage;
7119
7558
  const propertyNames = [...usage.propertyNames];
7120
7559
  const missingPropertyNames = propertyNames.filter(
7121
- (propertyName5) => !usage.destructuring?.propertyNames.has(propertyName5)
7560
+ (propertyName6) => !usage.destructuring?.propertyNames.has(propertyName6)
7122
7561
  );
7123
- if (missingPropertyNames.some((propertyName5) => hasBinding(context, firstDirectMember, propertyName5))) {
7562
+ if (missingPropertyNames.some((propertyName6) => hasBinding(context, firstDirectMember, propertyName6))) {
7124
7563
  continue;
7125
7564
  }
7126
7565
  context.report({
@@ -7134,7 +7573,7 @@ var preferObjectDestructuringRule = {
7134
7573
  return null;
7135
7574
  }
7136
7575
  const memberFixes = usage.directMembers.map(
7137
- ({ member, propertyName: propertyName5 }) => fixer.replaceText(member, propertyName5)
7576
+ ({ member, propertyName: propertyName6 }) => fixer.replaceText(member, propertyName6)
7138
7577
  );
7139
7578
  if (usage.destructuring) {
7140
7579
  if (missingPropertyNames.length === 0) return memberFixes;
@@ -7173,7 +7612,7 @@ ${indentation}`;
7173
7612
  continue;
7174
7613
  }
7175
7614
  if (fromSameSource.length > 1) {
7176
- const names = new Set(fromSameSource.map(({ propertyName: propertyName5 }) => propertyName5));
7615
+ const names = new Set(fromSameSource.map(({ propertyName: propertyName6 }) => propertyName6));
7177
7616
  if (names.size > 1) {
7178
7617
  context.report({ node: binding.node, message: scopeUsageMessage(binding.sourceText, names) });
7179
7618
  continue;
@@ -7202,7 +7641,7 @@ ${indentation}`;
7202
7641
  const sourceText = context.sourceCode.getText(declarator.init);
7203
7642
  context.report({
7204
7643
  node: declarator.id,
7205
- message: `"${sourceText}" is an enum. Keep enum member accesses qualified instead of destructuring it. ${DOC6}`
7644
+ message: `"${sourceText}" is an enum. Keep enum member accesses qualified instead of destructuring it. ${DOC7}`
7206
7645
  });
7207
7646
  }
7208
7647
  recordDestructuringUsage(context, currentUsageScope(), node, isEnumValue);
@@ -7213,12 +7652,12 @@ ${indentation}`;
7213
7652
  if (group.length <= 1) {
7214
7653
  if (node.kind === "const" && selection.propertyNames.length === 1 && supportsSinglePropertySource(selection.source)) {
7215
7654
  const declarator = node.declarations[0];
7216
- const propertyName5 = selection.propertyNames[0];
7217
- if (declarator && propertyName5) {
7655
+ const propertyName6 = selection.propertyNames[0];
7656
+ if (declarator && propertyName6) {
7218
7657
  currentUsageScope()?.singleProperties.push({
7219
7658
  node: declarator.id,
7220
7659
  sourceText: selection.sourceText,
7221
- propertyName: propertyName5
7660
+ propertyName: propertyName6
7222
7661
  });
7223
7662
  }
7224
7663
  }
@@ -7248,7 +7687,7 @@ ${indentation}`;
7248
7687
  if (bindings.length === 0) return;
7249
7688
  const firstBinding = bindings[0];
7250
7689
  if (!firstBinding) return;
7251
- const sameSourceBindings = bindings.length > 1 && bindings.length === node.declarations.length && bindings.every(({ sourceText }) => sourceText === firstBinding.sourceText) && new Set(bindings.map(({ propertyName: propertyName5 }) => propertyName5)).size === bindings.length;
7690
+ const sameSourceBindings = bindings.length > 1 && bindings.length === node.declarations.length && bindings.every(({ sourceText }) => sourceText === firstBinding.sourceText) && new Set(bindings.map(({ propertyName: propertyName6 }) => propertyName6)).size === bindings.length;
7252
7691
  if (sameSourceBindings) {
7253
7692
  context.report({
7254
7693
  node,
@@ -7303,7 +7742,7 @@ ${indentation}`;
7303
7742
  };
7304
7743
 
7305
7744
  // eslint/rules/pure-function-extract.ts
7306
- import path47 from "path";
7745
+ import path49 from "path";
7307
7746
  var ROUTE_HANDLER_EXPORT_NAMES = /* @__PURE__ */ new Set([
7308
7747
  "GET",
7309
7748
  "POST",
@@ -7368,12 +7807,12 @@ var pureFunctionExtractRule = {
7368
7807
  },
7369
7808
  create(context) {
7370
7809
  const filename = context.filename;
7371
- const isRouteFile = path47.basename(filename) === "route.ts";
7810
+ const isRouteFile = path49.basename(filename) === "route.ts";
7372
7811
  const isComponentFile = filename.endsWith(".tsx") || filename.endsWith(".jsx");
7373
7812
  const sourceRoot = sourceRootOf(context);
7374
- const relative = path47.relative(sourceRoot, filename);
7813
+ const relative = path49.relative(sourceRoot, filename);
7375
7814
  if (relative.startsWith("..")) return {};
7376
- const segments = relative.split(path47.sep);
7815
+ const segments = relative.split(path49.sep);
7377
7816
  const folders = segments.slice(0, -1);
7378
7817
  const isHookSupportFile = folders.includes("hooks") && /\.(?:[cm]?[jt]s)$/.test(filename);
7379
7818
  if (!isComponentFile && !isRouteFile && !isHookSupportFile) return {};
@@ -7433,15 +7872,15 @@ var pureFunctionExtractRule = {
7433
7872
  };
7434
7873
 
7435
7874
  // eslint/rules/repeated-numeric-value.ts
7436
- import path48 from "path";
7875
+ import path50 from "path";
7437
7876
  function isNonProductionFile(file, sourceRoot) {
7438
- const relative = path48.relative(sourceRoot, file);
7439
- const segments = relative.split(path48.sep);
7440
- const basename = path48.basename(file);
7877
+ const relative = path50.relative(sourceRoot, file);
7878
+ const segments = relative.split(path50.sep);
7879
+ const basename = path50.basename(file);
7441
7880
  return /\.(?:test|spec|mock)\.[^.]+$/.test(basename) || segments.some((segment) => segment === "__tests__" || segment === "__mocks__" || segment === "mocks");
7442
7881
  }
7443
7882
  function isCanonicalConstantFile(file, sourceRoot) {
7444
- const segments = path48.relative(sourceRoot, file).split(path48.sep);
7883
+ const segments = path50.relative(sourceRoot, file).split(path50.sep);
7445
7884
  return segments.includes("constants") || segments[0] === "config";
7446
7885
  }
7447
7886
  function groupKey(literal) {
@@ -7457,7 +7896,7 @@ var repeatedNumericValueRule = {
7457
7896
  },
7458
7897
  create(context) {
7459
7898
  const sourceRoot = sourceRootOf(context);
7460
- const file = path48.resolve(context.filename);
7899
+ const file = path50.resolve(context.filename);
7461
7900
  if (isNonProductionFile(file, sourceRoot) || isCanonicalConstantFile(file, sourceRoot)) return {};
7462
7901
  const index = getProjectIndex(sourceRoot);
7463
7902
  if (!index) return {};
@@ -7494,11 +7933,11 @@ var repeatedNumericValueRule = {
7494
7933
  };
7495
7934
 
7496
7935
  // eslint/rules/repeated-semantic-literal.ts
7497
- import path50 from "path";
7936
+ import path52 from "path";
7498
7937
 
7499
7938
  // eslint/rules/imported-enum-literals.ts
7500
- import path49 from "path";
7501
- import ts11 from "typescript";
7939
+ import path51 from "path";
7940
+ import ts12 from "typescript";
7502
7941
  var columnMethods2 = /* @__PURE__ */ new Set([
7503
7942
  "eq",
7504
7943
  "neq",
@@ -7514,13 +7953,13 @@ var columnMethods2 = /* @__PURE__ */ new Set([
7514
7953
  "filter",
7515
7954
  "not"
7516
7955
  ]);
7517
- function memberName6(name) {
7518
- if (ts11.isIdentifier(name) || ts11.isStringLiteral(name)) return name.text;
7956
+ function memberName7(name) {
7957
+ if (ts12.isIdentifier(name) || ts12.isStringLiteral(name)) return name.text;
7519
7958
  return void 0;
7520
7959
  }
7521
7960
  function isWithin3(root, file) {
7522
- const relative = path49.relative(root, file);
7523
- return relative === "" || !relative.startsWith("..") && !path49.isAbsolute(relative);
7961
+ const relative = path51.relative(root, file);
7962
+ return relative === "" || !relative.startsWith("..") && !path51.isAbsolute(relative);
7524
7963
  }
7525
7964
  function domainOf(name) {
7526
7965
  if (name.endsWith("ColumnEnum")) return "column";
@@ -7530,23 +7969,23 @@ function domainOf(name) {
7530
7969
  function importedEnums(file, checker, sourceRoot, importedNames) {
7531
7970
  const matches = /* @__PURE__ */ new Map();
7532
7971
  for (const statement of file.statements) {
7533
- if (!ts11.isImportDeclaration(statement) || !statement.importClause?.namedBindings || !ts11.isNamedImports(statement.importClause.namedBindings)) {
7972
+ if (!ts12.isImportDeclaration(statement) || !statement.importClause?.namedBindings || !ts12.isNamedImports(statement.importClause.namedBindings)) {
7534
7973
  continue;
7535
7974
  }
7536
7975
  for (const specifier of statement.importClause.namedBindings.elements) {
7537
7976
  if (!importedNames.has(specifier.name.text)) continue;
7538
7977
  const symbol = checker.getSymbolAtLocation(specifier.name);
7539
7978
  if (!symbol) continue;
7540
- const resolved = symbol.flags === ts11.SymbolFlags.Alias ? checker.getAliasedSymbol(symbol) : symbol;
7979
+ const resolved = symbol.flags === ts12.SymbolFlags.Alias ? checker.getAliasedSymbol(symbol) : symbol;
7541
7980
  for (const declaration of resolved.declarations ?? []) {
7542
- if (!ts11.isEnumDeclaration(declaration)) continue;
7543
- const declarationFile = path49.resolve(declaration.getSourceFile().fileName);
7981
+ if (!ts12.isEnumDeclaration(declaration)) continue;
7982
+ const declarationFile = path51.resolve(declaration.getSourceFile().fileName);
7544
7983
  if (!isWithin3(sourceRoot, declarationFile)) continue;
7545
7984
  const domain = domainOf(declaration.name.text);
7546
7985
  if (!domain) continue;
7547
7986
  for (const member of declaration.members) {
7548
- if (!member.initializer || !ts11.isStringLiteral(member.initializer)) continue;
7549
- const name = memberName6(member.name);
7987
+ if (!member.initializer || !ts12.isStringLiteral(member.initializer)) continue;
7988
+ const name = memberName7(member.name);
7550
7989
  if (!name) continue;
7551
7990
  const entries = matches.get(member.initializer.text) ?? [];
7552
7991
  entries.push({
@@ -7562,25 +8001,25 @@ function importedEnums(file, checker, sourceRoot, importedNames) {
7562
8001
  return matches;
7563
8002
  }
7564
8003
  function isPathname2(node) {
7565
- return ts11.isPropertyAccessExpression(node) && node.name.text === "pathname";
8004
+ return ts12.isPropertyAccessExpression(node) && node.name.text === "pathname";
7566
8005
  }
7567
8006
  function domainForUse(node) {
7568
8007
  const parent = node.parent;
7569
- if (ts11.isPropertyAssignment(parent) && parent.initializer === node && memberName6(parent.name) === "path") {
8008
+ if (ts12.isPropertyAssignment(parent) && parent.initializer === node && memberName7(parent.name) === "path") {
7570
8009
  return "route";
7571
8010
  }
7572
- if (ts11.isCallExpression(parent) && parent.arguments[0] === node && ts11.isPropertyAccessExpression(parent.expression)) {
8011
+ if (ts12.isCallExpression(parent) && parent.arguments[0] === node && ts12.isPropertyAccessExpression(parent.expression)) {
7573
8012
  const { expression, name } = parent.expression;
7574
8013
  if (columnMethods2.has(name.text)) return "column";
7575
8014
  if (name.text === "startsWith" && isPathname2(expression)) return "route";
7576
8015
  }
7577
- if (ts11.isBinaryExpression(parent) && (parent.operatorToken.kind === ts11.SyntaxKind.EqualsEqualsEqualsToken || parent.operatorToken.kind === ts11.SyntaxKind.ExclamationEqualsEqualsToken) && (parent.left === node && isPathname2(parent.right) || parent.right === node && isPathname2(parent.left))) {
8016
+ if (ts12.isBinaryExpression(parent) && (parent.operatorToken.kind === ts12.SyntaxKind.EqualsEqualsEqualsToken || parent.operatorToken.kind === ts12.SyntaxKind.ExclamationEqualsEqualsToken) && (parent.left === node && isPathname2(parent.right) || parent.right === node && isPathname2(parent.left))) {
7578
8017
  return "route";
7579
8018
  }
7580
8019
  return void 0;
7581
8020
  }
7582
8021
  function importedEnumLiteralUses(context, root) {
7583
- const filename = path49.resolve(context.filename);
8022
+ const filename = path51.resolve(context.filename);
7584
8023
  if (!isWithin3(root, filename)) return [];
7585
8024
  const services = typedParserServices(context.sourceCode.parserServices);
7586
8025
  if (!services) return [];
@@ -7596,7 +8035,7 @@ function importedEnumLiteralUses(context, root) {
7596
8035
  if (matches.size === 0) return [];
7597
8036
  const uses = [];
7598
8037
  const visit = (node) => {
7599
- if (ts11.isStringLiteral(node)) {
8038
+ if (ts12.isStringLiteral(node)) {
7600
8039
  const domain = domainForUse(node);
7601
8040
  const candidates = matches.get(node.text)?.filter((entry) => entry.domain === domain) ?? [];
7602
8041
  if (candidates.length === 1) {
@@ -7613,14 +8052,14 @@ function importedEnumLiteralUses(context, root) {
7613
8052
  }
7614
8053
  }
7615
8054
  }
7616
- ts11.forEachChild(node, visit);
8055
+ ts12.forEachChild(node, visit);
7617
8056
  };
7618
8057
  visit(file);
7619
8058
  return uses;
7620
8059
  }
7621
8060
 
7622
8061
  // eslint/rules/repeated-semantic-literal.ts
7623
- var DOC7 = "See docs/next-codebase-guide/rules/constants-rule.md";
8062
+ var DOC8 = "See docs/next-codebase-guide/rules/constants-rule.md";
7624
8063
  var closedDomainFamilies = /* @__PURE__ */ new Set(["api-route", "event", "storage"]);
7625
8064
  function canonicalMatches(use, canonical, sourceRoot) {
7626
8065
  if (use.kind !== canonical.kind || use.value !== canonical.value) return false;
@@ -7634,7 +8073,7 @@ function canonicalMatches(use, canonical, sourceRoot) {
7634
8073
  const semanticName2 = use.family.split(":")[1];
7635
8074
  if (!semanticName2 || !name.toLowerCase().includes(semanticName2.toLowerCase())) return false;
7636
8075
  const location = featureOf(canonical.file, sourceRoot);
7637
- return location === featureOf(use.file, sourceRoot) || path50.relative(sourceRoot, canonical.file).split(path50.sep)[0] === "constants";
8076
+ return location === featureOf(use.file, sourceRoot) || path52.relative(sourceRoot, canonical.file).split(path52.sep)[0] === "constants";
7638
8077
  }
7639
8078
  return false;
7640
8079
  }
@@ -7648,14 +8087,14 @@ function messageFor(use, matches, duplicateRouteDomains, existingRouteEnum, root
7648
8087
  const count = new Set(matches.map((match) => match.file)).size;
7649
8088
  const kind = use.kind === "string" ? "string" : "numeric";
7650
8089
  if (use.family === "api-route" && existingRouteEnum?.owner) {
7651
- const location = path50.relative(root, existingRouteEnum.file).replaceAll(path50.sep, "/");
7652
- return `The route ${formatValue(use)} repeats; add a member to existing ${existingRouteEnum.owner} in src/${location} and reuse it. ${DOC7}`;
8090
+ const location = path52.relative(root, existingRouteEnum.file).replaceAll(path52.sep, "/");
8091
+ return `The route ${formatValue(use)} repeats; add a member to existing ${existingRouteEnum.owner} in src/${location} and reuse it. ${DOC8}`;
7653
8092
  }
7654
8093
  if (count === 1) {
7655
- return `The ${kind} literal ${formatValue(use)} repeats in the same semantic role in this file. Extract a file-local const. ${DOC7}`;
8094
+ return `The ${kind} literal ${formatValue(use)} repeats in the same semantic role in this file. Extract a file-local const. ${DOC8}`;
7656
8095
  }
7657
8096
  const placement = use.family === "api-route" && duplicateRouteDomains.has(use.role) ? "a shared enum for this closed route domain" : "one shared const";
7658
- return `The ${kind} literal ${formatValue(use)} repeats in ${String(count)} production files for the same semantic role. Extract ${placement} at the consumers' CCF and import it. ${DOC7}`;
8097
+ return `The ${kind} literal ${formatValue(use)} repeats in ${String(count)} production files for the same semantic role. Extract ${placement} at the consumers' CCF and import it. ${DOC8}`;
7659
8098
  }
7660
8099
  var repeatedSemanticLiteralRule = {
7661
8100
  meta: {
@@ -7667,7 +8106,7 @@ var repeatedSemanticLiteralRule = {
7667
8106
  },
7668
8107
  create(context) {
7669
8108
  const root = sourceRootOf(context);
7670
- const file = path50.resolve(context.filename);
8109
+ const file = path52.resolve(context.filename);
7671
8110
  if (!isProductionSource(file, root)) return {};
7672
8111
  const project = getProjectIndex(root);
7673
8112
  if (!project?.modules.has(file)) return {};
@@ -7712,11 +8151,11 @@ var repeatedSemanticLiteralRule = {
7712
8151
  return {
7713
8152
  Program(node) {
7714
8153
  for (const use of imported) {
7715
- const relative = path50.relative(root, use.sourceFile).replaceAll(path50.sep, "/");
8154
+ const relative = path52.relative(root, use.sourceFile).replaceAll(path52.sep, "/");
7716
8155
  context.report({
7717
8156
  node,
7718
8157
  loc: { line: use.line, column: use.column },
7719
- message: `Reuse ${use.reference} from src/${relative} instead of raw ${JSON.stringify(use.value)}. ${DOC7}`
8158
+ message: `Reuse ${use.reference} from src/${relative} instead of raw ${JSON.stringify(use.value)}. ${DOC8}`
7720
8159
  });
7721
8160
  }
7722
8161
  for (const use of current) {
@@ -7727,11 +8166,11 @@ var repeatedSemanticLiteralRule = {
7727
8166
  if (candidates.length === 1) {
7728
8167
  const canonical = candidates[0];
7729
8168
  if (!canonical) continue;
7730
- const relative = path50.relative(root, canonical.file).replaceAll(path50.sep, "/");
8169
+ const relative = path52.relative(root, canonical.file).replaceAll(path52.sep, "/");
7731
8170
  context.report({
7732
8171
  node,
7733
8172
  loc: { line: use.line, column: use.column },
7734
- message: `Reuse ${canonicalName(canonical)} from src/${relative} instead of raw ${formatValue(use)}. ${DOC7}`
8173
+ message: `Reuse ${canonicalName(canonical)} from src/${relative} instead of raw ${formatValue(use)}. ${DOC8}`
7735
8174
  });
7736
8175
  continue;
7737
8176
  }
@@ -7740,11 +8179,11 @@ var repeatedSemanticLiteralRule = {
7740
8179
  const peers = groups.get(key) ?? [];
7741
8180
  if (peers.length < 2) {
7742
8181
  if (use.family === "api-route" && existingRouteEnum?.owner) {
7743
- const location = path50.relative(root, existingRouteEnum.file).replaceAll(path50.sep, "/");
8182
+ const location = path52.relative(root, existingRouteEnum.file).replaceAll(path52.sep, "/");
7744
8183
  context.report({
7745
8184
  node,
7746
8185
  loc: { line: use.line, column: use.column },
7747
- message: `The route ${formatValue(use)} belongs to existing ${existingRouteEnum.owner}; add a member in src/${location} and reuse it. ${DOC7}`
8186
+ message: `The route ${formatValue(use)} belongs to existing ${existingRouteEnum.owner}; add a member in src/${location} and reuse it. ${DOC8}`
7748
8187
  });
7749
8188
  continue;
7750
8189
  }
@@ -7753,7 +8192,7 @@ var repeatedSemanticLiteralRule = {
7753
8192
  context.report({
7754
8193
  node,
7755
8194
  loc: { line: use.line, column: use.column },
7756
- message: `The string literal ${formatValue(use)} is one of ${String(domain.size)} values in a closed ${use.family} domain. Declare the domain in a shared enum at the consumers' CCF and reuse it. ${DOC7}`
8195
+ message: `The string literal ${formatValue(use)} is one of ${String(domain.size)} values in a closed ${use.family} domain. Declare the domain in a shared enum at the consumers' CCF and reuse it. ${DOC8}`
7757
8196
  });
7758
8197
  }
7759
8198
  continue;
@@ -7952,7 +8391,7 @@ var repeatedStructureRule = {
7952
8391
 
7953
8392
  // eslint/rules/require-barrel-star-exports.ts
7954
8393
  import fs5 from "fs";
7955
- import path51 from "path";
8394
+ import path53 from "path";
7956
8395
  var SUPPORT_FOLDERS3 = /* @__PURE__ */ new Set(["constants", "types", "schemas"]);
7957
8396
  var INDEX_NAMES = /* @__PURE__ */ new Set(["index.ts", "index.tsx", "index.mts", "index.cts"]);
7958
8397
  var MODULE_EXTENSIONS3 = [".ts", ".tsx", ".mts", ".cts", ".js", ".jsx", ".mjs", ".cjs"];
@@ -7960,9 +8399,9 @@ function resolveSiblingModule(indexFile, specifier) {
7960
8399
  if (!specifier.startsWith("./")) return void 0;
7961
8400
  const relative = specifier.slice(2);
7962
8401
  if (!relative || relative.includes("/")) return void 0;
7963
- const directory = path51.dirname(indexFile);
7964
- const direct = path51.resolve(directory, relative);
7965
- const candidates = path51.extname(direct) ? [direct] : MODULE_EXTENSIONS3.map((extension) => `${direct}${extension}`);
8402
+ const directory = path53.dirname(indexFile);
8403
+ const direct = path53.resolve(directory, relative);
8404
+ const candidates = path53.extname(direct) ? [direct] : MODULE_EXTENSIONS3.map((extension) => `${direct}${extension}`);
7966
8405
  return candidates.find((candidate) => fs5.existsSync(candidate) && fs5.statSync(candidate).isFile());
7967
8406
  }
7968
8407
  var requireBarrelStarExportsRule = {
@@ -7975,9 +8414,9 @@ var requireBarrelStarExportsRule = {
7975
8414
  fixable: "code"
7976
8415
  },
7977
8416
  create(context) {
7978
- const filename = path51.resolve(context.filename);
7979
- if (!INDEX_NAMES.has(path51.basename(filename))) return {};
7980
- if (!SUPPORT_FOLDERS3.has(path51.basename(path51.dirname(filename)))) return {};
8417
+ const filename = path53.resolve(context.filename);
8418
+ if (!INDEX_NAMES.has(path53.basename(filename))) return {};
8419
+ if (!SUPPORT_FOLDERS3.has(path53.basename(path53.dirname(filename)))) return {};
7981
8420
  return {
7982
8421
  ExportNamedDeclaration(node) {
7983
8422
  const sourceNode = node.source;
@@ -8030,7 +8469,7 @@ var requireBarrelStarExportsRule = {
8030
8469
  };
8031
8470
 
8032
8471
  // eslint/rules/root-support-placement.ts
8033
- import path52 from "path";
8472
+ import path54 from "path";
8034
8473
  function isSupportFolder(value) {
8035
8474
  return value === "utils" || value === "types" || value === "schemas" || value === "constants";
8036
8475
  }
@@ -8063,7 +8502,7 @@ var rootSupportPlacementRule = {
8063
8502
  },
8064
8503
  create(context) {
8065
8504
  const sourceRoot = sourceRootOf(context);
8066
- const file = path52.resolve(context.filename);
8505
+ const file = path54.resolve(context.filename);
8067
8506
  const segments = segmentsOf(file, sourceRoot);
8068
8507
  const folderSegments = folderSegmentsOf(file, sourceRoot);
8069
8508
  const supportFolder = folderSegments[folderSegments.length - 1];
@@ -8109,8 +8548,104 @@ var rootSupportPlacementRule = {
8109
8548
  };
8110
8549
 
8111
8550
  // eslint/rules/route-handler-shape.ts
8112
- import path53 from "path";
8113
- import ts12 from "typescript";
8551
+ import path56 from "path";
8552
+ import ts13 from "typescript";
8553
+
8554
+ // eslint/rules/route-single-use-delegation.ts
8555
+ import path55 from "path";
8556
+ function responseCall(expression) {
8557
+ if (!expression) return void 0;
8558
+ if (expression.type === "AwaitExpression") return responseCall(expression.argument);
8559
+ if (expression.type === "CallExpression" && expression.callee.type === "Identifier") return expression;
8560
+ if (expression.type !== "ObjectExpression") return void 0;
8561
+ const dataProperties = expression.properties.filter(
8562
+ (property) => property.type === "Property" && !property.computed && (property.key.type === "Identifier" && property.key.name === "data" || property.key.type === "Literal" && property.key.value === "data")
8563
+ );
8564
+ if (dataProperties.length !== 1) return void 0;
8565
+ const otherProperties = expression.properties.filter((property) => !dataProperties.includes(property));
8566
+ if (otherProperties.some(
8567
+ (property) => property.type !== "Property" || property.value.type !== "Literal" || property.computed
8568
+ )) {
8569
+ return void 0;
8570
+ }
8571
+ return responseCall(dataProperties[0]?.type === "Property" ? dataProperties[0].value : void 0);
8572
+ }
8573
+ function soleDelegation(handler) {
8574
+ if (handler.body.type !== "BlockStatement") return responseCall(handler.body);
8575
+ const statements = handler.body.body;
8576
+ if (statements.length === 1 && statements[0]?.type === "ReturnStatement") {
8577
+ return responseCall(statements[0].argument);
8578
+ }
8579
+ const [declaration, returned] = statements;
8580
+ if (statements.length !== 2 || declaration?.type !== "VariableDeclaration" || declaration.declarations.length !== 1 || returned?.type !== "ReturnStatement") {
8581
+ return void 0;
8582
+ }
8583
+ const variable = declaration.declarations[0];
8584
+ if (variable?.id.type !== "Identifier") return void 0;
8585
+ const call = responseCall(variable.init);
8586
+ if (!call || !returned.argument) return void 0;
8587
+ if (returned.argument.type === "Identifier" && returned.argument.name === variable.id.name) return call;
8588
+ if (returned.argument.type !== "ObjectExpression") return void 0;
8589
+ const properties = returned.argument.properties;
8590
+ if (properties.length !== 1 || properties[0]?.type !== "Property") return void 0;
8591
+ const property = properties[0];
8592
+ const key = property.key;
8593
+ const isData = !property.computed && (key.type === "Identifier" && key.name === "data" || key.type === "Literal" && key.value === "data");
8594
+ return isData && property.value.type === "Identifier" && property.value.name === variable.id.name ? call : void 0;
8595
+ }
8596
+ function isTestFile2(file) {
8597
+ return /(?:\.test|\.spec)\.[cm]?[jt]sx?$/.test(file) || path55.normalize(file).split(path55.sep).includes("__tests__");
8598
+ }
8599
+ function functionSource(index, file, name, sourceRoot, visited = /* @__PURE__ */ new Set()) {
8600
+ if (visited.has(file)) return void 0;
8601
+ visited.add(file);
8602
+ const module = index.modules.get(file);
8603
+ if (!module) return void 0;
8604
+ if (module.exports.some((entry) => entry.name === name && entry.kind === "function")) return file;
8605
+ if (!module.exports.some((entry) => entry.name === name) && !module.reexports.some((entry) => entry.names.length === 0)) {
8606
+ return void 0;
8607
+ }
8608
+ for (const entry of module.reexports) {
8609
+ if (entry.names.length > 0 && !entry.names.includes(name)) continue;
8610
+ const target = resolveSpecifier(file, entry.specifier, sourceRoot);
8611
+ if (!target) continue;
8612
+ const original = functionSource(index, target, name, sourceRoot, visited);
8613
+ if (original) return original;
8614
+ }
8615
+ return void 0;
8616
+ }
8617
+ function singleUseResponseDelegate(context, handler) {
8618
+ const call = soleDelegation(handler);
8619
+ if (call?.callee.type !== "Identifier") return void 0;
8620
+ const name = call.callee.name;
8621
+ const sourceRoot = sourceRootOf(context);
8622
+ const index = getProjectIndex(sourceRoot);
8623
+ if (!index) return void 0;
8624
+ for (const statement of context.sourceCode.ast.body) {
8625
+ if (statement.type !== "ImportDeclaration" || typeof statement.source.value !== "string") continue;
8626
+ const target = resolveSpecifier(context.filename, statement.source.value, sourceRoot);
8627
+ if (target === void 0 || target === context.filename) continue;
8628
+ for (const specifier of statement.specifiers) {
8629
+ if (specifier.type !== "ImportSpecifier" || specifier.local.name !== name) continue;
8630
+ const original = specifier.imported.type === "Identifier" ? specifier.imported.name : String(specifier.imported.value);
8631
+ const source = functionSource(index, target, original, sourceRoot);
8632
+ if (!source) continue;
8633
+ const bindings = context.sourceCode.getDeclaredVariables(specifier);
8634
+ if (!bindings.some((binding) => binding.references.length === 1)) continue;
8635
+ const consumers = index.symbolConsumers.get(symbolKey(source, original));
8636
+ if (!consumers?.has(context.filename)) continue;
8637
+ const activeConsumers = [...consumers].filter((consumer) => {
8638
+ if (isTestFile2(consumer)) return false;
8639
+ const module = index.modules.get(consumer);
8640
+ return !(module && module.reexports.length > 0 && module.imports.length === module.reexports.length && module.exports.every((entry) => entry.kind === "other"));
8641
+ });
8642
+ if (activeConsumers.length === 1 && activeConsumers[0] === context.filename) return original;
8643
+ }
8644
+ }
8645
+ return void 0;
8646
+ }
8647
+
8648
+ // eslint/rules/route-handler-shape.ts
8114
8649
  var HTTP_METHODS2 = /* @__PURE__ */ new Set(["GET", "POST", "PUT", "PATCH", "DELETE", "HEAD", "OPTIONS"]);
8115
8650
  var REQUIRED_BOUNDARY = "withResponse";
8116
8651
  function isFunctionLike(node) {
@@ -8128,33 +8663,33 @@ function findHandler(node) {
8128
8663
  return void 0;
8129
8664
  }
8130
8665
  function isLoop(node) {
8131
- return ts12.isForStatement(node) || ts12.isForOfStatement(node) || ts12.isForInStatement(node) || ts12.isWhileStatement(node) || ts12.isDoStatement(node);
8666
+ return ts13.isForStatement(node) || ts13.isForOfStatement(node) || ts13.isForInStatement(node) || ts13.isWhileStatement(node) || ts13.isDoStatement(node);
8132
8667
  }
8133
8668
  function isFunctionBoundary(node) {
8134
- return ts12.isFunctionExpression(node) || ts12.isArrowFunction(node) || ts12.isFunctionDeclaration(node);
8669
+ return ts13.isFunctionExpression(node) || ts13.isArrowFunction(node) || ts13.isFunctionDeclaration(node);
8135
8670
  }
8136
8671
  function analyzeHandlerBody(body, sourceText) {
8137
8672
  const start = body.range?.[0] ?? 0;
8138
8673
  const end = body.range?.[1] ?? sourceText.length;
8139
- const sourceFile = ts12.createSourceFile(
8674
+ const sourceFile = ts13.createSourceFile(
8140
8675
  "route.ts",
8141
8676
  sourceText.slice(start, end),
8142
- ts12.ScriptTarget.Latest,
8677
+ ts13.ScriptTarget.Latest,
8143
8678
  true,
8144
- ts12.ScriptKind.TS
8679
+ ts13.ScriptKind.TS
8145
8680
  );
8146
8681
  const kinds = /* @__PURE__ */ new Set();
8147
8682
  const calledNames = /* @__PURE__ */ new Set();
8148
8683
  const visit = (node) => {
8149
- if (ts12.isTryStatement(node)) kinds.add("try");
8684
+ if (ts13.isTryStatement(node)) kinds.add("try");
8150
8685
  if (isLoop(node)) kinds.add("loop");
8151
- if (ts12.isIfStatement(node)) kinds.add("if");
8152
- if (ts12.isCallExpression(node) && ts12.isPropertyAccessExpression(node.expression) && node.expression.name.text === "map") {
8686
+ if (ts13.isIfStatement(node)) kinds.add("if");
8687
+ if (ts13.isCallExpression(node) && ts13.isPropertyAccessExpression(node.expression) && node.expression.name.text === "map") {
8153
8688
  kinds.add("map");
8154
8689
  }
8155
- if (ts12.isCallExpression(node) && ts12.isIdentifier(node.expression)) calledNames.add(node.expression.text);
8690
+ if (ts13.isCallExpression(node) && ts13.isIdentifier(node.expression)) calledNames.add(node.expression.text);
8156
8691
  if (isFunctionBoundary(node)) return;
8157
- ts12.forEachChild(node, visit);
8692
+ ts13.forEachChild(node, visit);
8158
8693
  };
8159
8694
  visit(sourceFile);
8160
8695
  return { kinds, calledNames };
@@ -8194,7 +8729,7 @@ var routeHandlerShapeRule = {
8194
8729
  }
8195
8730
  },
8196
8731
  create(context) {
8197
- if (path53.basename(context.filename) !== "route.ts") return {};
8732
+ if (path56.basename(context.filename) !== "route.ts") return {};
8198
8733
  const sourceText = context.sourceCode.text;
8199
8734
  function reportUnwrapped(node, name) {
8200
8735
  context.report({
@@ -8217,6 +8752,13 @@ var routeHandlerShapeRule = {
8217
8752
  });
8218
8753
  return;
8219
8754
  }
8755
+ const singleUseDelegate = singleUseResponseDelegate(context, handler);
8756
+ if (singleUseDelegate) {
8757
+ context.report({
8758
+ node,
8759
+ message: `Handler "${name}" delegates its entire response to single-use utility "${singleUseDelegate}"; inline its workflow in route.ts. See docs/next-codebase-guide/rules/route-handler-rule.md`
8760
+ });
8761
+ }
8220
8762
  const { kinds, calledNames } = analyzeHandlerBody(handler.body, sourceText);
8221
8763
  for (const kind of kinds) {
8222
8764
  context.report({
@@ -8253,7 +8795,7 @@ var routeHandlerShapeRule = {
8253
8795
  };
8254
8796
 
8255
8797
  // eslint/rules/schema-casing.ts
8256
- import path54 from "path";
8798
+ import path57 from "path";
8257
8799
  function isCamelCase(name) {
8258
8800
  return /^[a-z][a-zA-Z0-9]*$/.test(name);
8259
8801
  }
@@ -8281,9 +8823,9 @@ var schemaCasingRule = {
8281
8823
  }
8282
8824
  },
8283
8825
  create(context) {
8284
- const filename = path54.resolve(context.filename);
8826
+ const filename = path57.resolve(context.filename);
8285
8827
  const sourceRoot = sourceRootOf(context);
8286
- if (!filename.startsWith(sourceRoot + path54.sep)) return {};
8828
+ if (!filename.startsWith(sourceRoot + path57.sep)) return {};
8287
8829
  let zodLocalName;
8288
8830
  return {
8289
8831
  ImportDeclaration(node) {
@@ -8315,39 +8857,39 @@ var schemaCasingRule = {
8315
8857
  };
8316
8858
 
8317
8859
  // eslint/rules/sole-state-owner.ts
8318
- import path55 from "path";
8319
- import ts13 from "typescript";
8860
+ import path58 from "path";
8861
+ import ts14 from "typescript";
8320
8862
  function findStateHooks(node) {
8321
8863
  const hooks = [];
8322
8864
  const visit = (child) => {
8323
- if (ts13.isCallExpression(child) && ts13.isIdentifier(child.expression) && child.expression.text === "useState") {
8324
- if (ts13.isVariableDeclaration(child.parent)) {
8865
+ if (ts14.isCallExpression(child) && ts14.isIdentifier(child.expression) && child.expression.text === "useState") {
8866
+ if (ts14.isVariableDeclaration(child.parent)) {
8325
8867
  const { name } = child.parent;
8326
- if (ts13.isArrayBindingPattern(name) && name.elements.length >= 2) {
8868
+ if (ts14.isArrayBindingPattern(name) && name.elements.length >= 2) {
8327
8869
  const value = name.elements[0];
8328
8870
  const updater = name.elements[1];
8329
- if (value && updater && ts13.isBindingElement(value) && ts13.isBindingElement(updater)) {
8871
+ if (value && updater && ts14.isBindingElement(value) && ts14.isBindingElement(updater)) {
8330
8872
  const valueName = value.name;
8331
8873
  const updaterName = updater.name;
8332
- if (ts13.isIdentifier(valueName) && ts13.isIdentifier(updaterName)) {
8874
+ if (ts14.isIdentifier(valueName) && ts14.isIdentifier(updaterName)) {
8333
8875
  hooks.push({ value: valueName.text, updater: updaterName.text });
8334
8876
  }
8335
8877
  }
8336
8878
  }
8337
8879
  }
8338
8880
  }
8339
- ts13.forEachChild(child, visit);
8881
+ ts14.forEachChild(child, visit);
8340
8882
  };
8341
8883
  visit(node);
8342
8884
  return hooks;
8343
8885
  }
8344
8886
  function isHookUsage(node, hook) {
8345
- if (ts13.isCallExpression(node) && ts13.isIdentifier(node.expression) && node.expression.text === hook.updater) {
8887
+ if (ts14.isCallExpression(node) && ts14.isIdentifier(node.expression) && node.expression.text === hook.updater) {
8346
8888
  return "updater";
8347
8889
  }
8348
- if (ts13.isIdentifier(node) && node.text === hook.value) {
8890
+ if (ts14.isIdentifier(node) && node.text === hook.value) {
8349
8891
  const parent = node.parent;
8350
- if (ts13.isBindingElement(parent) || ts13.isPropertyAccessExpression(parent) || ts13.isShorthandPropertyAssignment(parent)) {
8892
+ if (ts14.isBindingElement(parent) || ts14.isPropertyAccessExpression(parent) || ts14.isShorthandPropertyAssignment(parent)) {
8351
8893
  return void 0;
8352
8894
  }
8353
8895
  return "value";
@@ -8357,16 +8899,16 @@ function isHookUsage(node, hook) {
8357
8899
  function topLevelJsxChildren(initial) {
8358
8900
  if (!initial) return void 0;
8359
8901
  let expression = initial;
8360
- while (ts13.isParenthesizedExpression(expression)) expression = expression.expression;
8361
- if (ts13.isJsxFragment(expression)) {
8902
+ while (ts14.isParenthesizedExpression(expression)) expression = expression.expression;
8903
+ if (ts14.isJsxFragment(expression)) {
8362
8904
  const children = expression.children.filter(
8363
- (c) => !ts13.isJsxText(c) && !ts13.isJsxSpreadAttribute(c)
8905
+ (c) => !ts14.isJsxText(c) && !ts14.isJsxSpreadAttribute(c)
8364
8906
  );
8365
8907
  return { root: expression, children };
8366
8908
  }
8367
- if (ts13.isJsxElement(expression)) {
8909
+ if (ts14.isJsxElement(expression)) {
8368
8910
  const children = expression.children.filter(
8369
- (c) => !ts13.isJsxText(c) && !ts13.isJsxSpreadAttribute(c)
8911
+ (c) => !ts14.isJsxText(c) && !ts14.isJsxSpreadAttribute(c)
8370
8912
  );
8371
8913
  return { root: expression, children };
8372
8914
  }
@@ -8380,8 +8922,8 @@ function collectUsesIn(child, hook) {
8380
8922
  positions.push(node);
8381
8923
  count += 1;
8382
8924
  }
8383
- if (ts13.isFunctionDeclaration(node) || ts13.isClassDeclaration(node)) return;
8384
- ts13.forEachChild(node, visit);
8925
+ if (ts14.isFunctionDeclaration(node) || ts14.isClassDeclaration(node)) return;
8926
+ ts14.forEachChild(node, visit);
8385
8927
  };
8386
8928
  visit(child);
8387
8929
  return { positions, count };
@@ -8395,7 +8937,7 @@ var soleStateOwnerRule = {
8395
8937
  }
8396
8938
  },
8397
8939
  create(context) {
8398
- const filename = path55.resolve(context.filename);
8940
+ const filename = path58.resolve(context.filename);
8399
8941
  if (!filename.endsWith(".tsx") && !filename.endsWith(".jsx")) return {};
8400
8942
  const text = context.sourceCode.text;
8401
8943
  const components = parseComponentInfo(text, filename);
@@ -8420,18 +8962,18 @@ var soleStateOwnerRule = {
8420
8962
  }
8421
8963
  };
8422
8964
  function analyzeSoleOwner(declaration, hook) {
8423
- const body = ts13.isFunctionDeclaration(declaration) ? declaration.body : void 0;
8424
- if (!body || !ts13.isBlock(body)) return void 0;
8965
+ const body = ts14.isFunctionDeclaration(declaration) ? declaration.body : void 0;
8966
+ if (!body || !ts14.isBlock(body)) return void 0;
8425
8967
  const returns = [];
8426
8968
  const visit = (node) => {
8427
- if (node !== body && (ts13.isFunctionLike(node) || ts13.isClassLike(node))) return;
8428
- if (ts13.isReturnStatement(node)) returns.push(node);
8429
- ts13.forEachChild(node, visit);
8969
+ if (node !== body && (ts14.isFunctionLike(node) || ts14.isClassLike(node))) return;
8970
+ if (ts14.isReturnStatement(node)) returns.push(node);
8971
+ ts14.forEachChild(node, visit);
8430
8972
  };
8431
8973
  visit(body);
8432
8974
  if (returns.length !== 1) return void 0;
8433
8975
  const single = returns[0];
8434
- if (!single?.expression || !ts13.isExpression(single.expression)) return void 0;
8976
+ if (!single?.expression || !ts14.isExpression(single.expression)) return void 0;
8435
8977
  const returnExpression = single.expression;
8436
8978
  const root = topLevelJsxChildren(returnExpression);
8437
8979
  if (!root || root.children.length === 0) return void 0;
@@ -8454,11 +8996,11 @@ function usesOutsideJsx(declaration, hook, children) {
8454
8996
  let outside = false;
8455
8997
  const visit = (node) => {
8456
8998
  if (outside) return;
8457
- if (node !== declaration && (ts13.isFunctionDeclaration(node) || ts13.isClassDeclaration(node))) return;
8999
+ if (node !== declaration && (ts14.isFunctionDeclaration(node) || ts14.isClassDeclaration(node))) return;
8458
9000
  if (isHookUsage(node, hook)) {
8459
9001
  let current = node;
8460
9002
  let isInJsxChild = false;
8461
- while (!ts13.isSourceFile(current)) {
9003
+ while (!ts14.isSourceFile(current)) {
8462
9004
  if (children.includes(current)) {
8463
9005
  isInJsxChild = true;
8464
9006
  break;
@@ -8467,14 +9009,14 @@ function usesOutsideJsx(declaration, hook, children) {
8467
9009
  }
8468
9010
  if (!isInJsxChild) outside = true;
8469
9011
  }
8470
- ts13.forEachChild(node, visit);
9012
+ ts14.forEachChild(node, visit);
8471
9013
  };
8472
9014
  visit(declaration);
8473
9015
  return outside;
8474
9016
  }
8475
9017
 
8476
9018
  // eslint/rules/source-under-src.ts
8477
- import path56 from "path";
9019
+ import path59 from "path";
8478
9020
  var NON_SOURCE_ROOT_DIRS = /* @__PURE__ */ new Set([
8479
9021
  ".agents",
8480
9022
  ".cache",
@@ -8515,14 +9057,14 @@ var sourceUnderSrcRule = {
8515
9057
  }
8516
9058
  },
8517
9059
  create(context) {
8518
- const filename = path56.resolve(context.filename);
9060
+ const filename = path59.resolve(context.filename);
8519
9061
  if (!MODULE_EXTENSION.test(filename)) return {};
8520
- const relative = path56.relative(context.cwd, filename).replace(/\\/g, "/");
9062
+ const relative = path59.relative(context.cwd, filename).replace(/\\/g, "/");
8521
9063
  if (relative === "src" || relative.startsWith("src/")) return {};
8522
9064
  const topLevel = relative.split("/")[0] ?? "";
8523
9065
  if (NON_SOURCE_ROOT_DIRS.has(topLevel)) return {};
8524
9066
  if (!relative.includes("/")) {
8525
- const basename = path56.basename(filename);
9067
+ const basename = path59.basename(filename);
8526
9068
  if (CONFIG_FILE.test(basename) || DECLARATION_FILE.test(basename) || basename.startsWith(".")) return {};
8527
9069
  }
8528
9070
  return {
@@ -8538,7 +9080,7 @@ var sourceUnderSrcRule = {
8538
9080
  };
8539
9081
 
8540
9082
  // eslint/rules/stay-flat.ts
8541
- import path57 from "path";
9083
+ import path60 from "path";
8542
9084
  var stayFlatRule = {
8543
9085
  meta: {
8544
9086
  schema: [],
@@ -8549,7 +9091,7 @@ var stayFlatRule = {
8549
9091
  },
8550
9092
  create(context) {
8551
9093
  const sourceRoot = sourceRootOf(context);
8552
- const file = path57.resolve(context.filename);
9094
+ const file = path60.resolve(context.filename);
8553
9095
  const segments = segmentsOf(file, sourceRoot);
8554
9096
  if (segments.length !== 3 || segments[0] !== "features") return {};
8555
9097
  const index = getProjectIndex(sourceRoot);
@@ -8589,7 +9131,7 @@ var stayFlatRule = {
8589
9131
  };
8590
9132
 
8591
9133
  // eslint/rules/support-file-placement.ts
8592
- import path58 from "path";
9134
+ import path61 from "path";
8593
9135
  var CONFIG_OWNED_FOLDERS = /* @__PURE__ */ new Set(["types", "constants"]);
8594
9136
  var EXPORT_KIND_BY_SUPPORT_FOLDER = /* @__PURE__ */ new Map([
8595
9137
  ["constants", "constant"],
@@ -8614,7 +9156,7 @@ var supportFilePlacementRule = {
8614
9156
  },
8615
9157
  create(context) {
8616
9158
  const sourceRoot = sourceRootOf(context);
8617
- const supportFile = path58.resolve(context.filename);
9159
+ const supportFile = path61.resolve(context.filename);
8618
9160
  const currentFolder = folderSegmentsOf(supportFile, sourceRoot);
8619
9161
  const supportFolder = currentFolder[currentFolder.length - 1];
8620
9162
  if (supportFolder === void 0 || !SUPPORT_FOLDERS.has(supportFolder)) return {};
@@ -8668,7 +9210,7 @@ var supportFilePlacementRule = {
8668
9210
 
8669
9211
  // eslint/rules/support-folder-shape.ts
8670
9212
  import fs6 from "fs";
8671
- import path59 from "path";
9213
+ import path62 from "path";
8672
9214
  var SUPPORT_FOLDERS4 = /* @__PURE__ */ new Set(["constants", "types", "schemas"]);
8673
9215
  var INDEX_NAMES2 = /* @__PURE__ */ new Set(["index.ts", "index.tsx", "index.mts", "index.cts"]);
8674
9216
  var supportFolderShapeRule = {
@@ -8680,12 +9222,12 @@ var supportFolderShapeRule = {
8680
9222
  }
8681
9223
  },
8682
9224
  create(context) {
8683
- const filename = path59.resolve(context.filename);
8684
- const baseName = path59.basename(filename);
9225
+ const filename = path62.resolve(context.filename);
9226
+ const baseName = path62.basename(filename);
8685
9227
  if (!INDEX_NAMES2.has(baseName)) return {};
8686
- const folder = path59.basename(path59.dirname(filename));
9228
+ const folder = path62.basename(path62.dirname(filename));
8687
9229
  if (!SUPPORT_FOLDERS4.has(folder)) return {};
8688
- const directory = path59.dirname(filename);
9230
+ const directory = path62.dirname(filename);
8689
9231
  let entries;
8690
9232
  try {
8691
9233
  entries = fs6.readdirSync(directory);
@@ -8703,7 +9245,7 @@ var supportFolderShapeRule = {
8703
9245
  for (const match of source.matchAll(exportPattern)) {
8704
9246
  hasAnyReExport = true;
8705
9247
  const specifier = match.groups?.specifier;
8706
- if (specifier?.startsWith(".")) exportedFiles.add(path59.basename(specifier));
9248
+ if (specifier?.startsWith(".")) exportedFiles.add(path62.basename(specifier));
8707
9249
  }
8708
9250
  const guide = `docs/next-codebase-guide/rules/${folder === "constants" ? "constants" : "types-and-schemas"}-rule.md`;
8709
9251
  if (siblingModules.length === 0) {
@@ -8882,24 +9424,24 @@ var baseLayerPairRule = {
8882
9424
 
8883
9425
  // eslint/rules/tailwind/css-entry-point.ts
8884
9426
  import { statSync as statSync4 } from "fs";
8885
- import path62 from "path";
9427
+ import path65 from "path";
8886
9428
 
8887
9429
  // eslint/rules/tailwind/source-files.ts
8888
- import { readdirSync as readdirSync3, readFileSync as readFileSync11, statSync as statSync3 } from "fs";
8889
- import path60 from "path";
9430
+ import { readdirSync as readdirSync5, readFileSync as readFileSync13, statSync as statSync3 } from "fs";
9431
+ import path63 from "path";
8890
9432
  var CSS_EXTENSIONS = [".css"];
8891
9433
  var MODULE_EXTENSIONS4 = [".ts", ".tsx", ".mts", ".cts", ".js", ".jsx", ".mjs", ".cjs"];
8892
9434
  var SOURCE_EXTENSIONS = [...MODULE_EXTENSIONS4, ...CSS_EXTENSIONS];
8893
9435
  function findFiles(dir, extensions) {
8894
9436
  let entries;
8895
9437
  try {
8896
- entries = readdirSync3(dir);
9438
+ entries = readdirSync5(dir);
8897
9439
  } catch {
8898
9440
  return [];
8899
9441
  }
8900
9442
  return entries.flatMap((entry) => {
8901
9443
  if (entry.startsWith(".") || entry === "node_modules") return [];
8902
- const entryPath = path60.join(dir, entry);
9444
+ const entryPath = path63.join(dir, entry);
8903
9445
  let stats;
8904
9446
  try {
8905
9447
  stats = statSync3(entryPath);
@@ -8907,7 +9449,7 @@ function findFiles(dir, extensions) {
8907
9449
  return [];
8908
9450
  }
8909
9451
  if (stats.isDirectory()) return findFiles(entryPath, extensions);
8910
- return extensions.includes(path60.extname(entry)) ? [entryPath] : [];
9452
+ return extensions.includes(path63.extname(entry)) ? [entryPath] : [];
8911
9453
  });
8912
9454
  }
8913
9455
  function cachedTextReader() {
@@ -8916,7 +9458,7 @@ function cachedTextReader() {
8916
9458
  let text = texts.get(file);
8917
9459
  if (text === void 0) {
8918
9460
  try {
8919
- text = readFileSync11(file, "utf8");
9461
+ text = readFileSync13(file, "utf8");
8920
9462
  } catch {
8921
9463
  text = "";
8922
9464
  }
@@ -8930,7 +9472,7 @@ function escapeRegExp(text) {
8930
9472
  }
8931
9473
 
8932
9474
  // eslint/rules/tailwind/stylesheet-graph.ts
8933
- import path61 from "path";
9475
+ import path64 from "path";
8934
9476
  function registersTailwind(text) {
8935
9477
  return /@import\s+(?:url\(\s*)?["']tailwindcss["']\s*\)?/i.test(text);
8936
9478
  }
@@ -8944,25 +9486,25 @@ function moduleImports(text, fileName) {
8944
9486
  return new RegExp(`(?:import|require)\\s*\\(?\\s*["'][^"']*${escaped}["']`, "i").test(text);
8945
9487
  }
8946
9488
  function resolveSpecifier2(fromFile, spec, sourceRoot) {
8947
- if (spec.startsWith("/")) return path61.resolve(spec);
8948
- if (spec.startsWith("./") || spec.startsWith("../")) return path61.resolve(path61.dirname(fromFile), spec);
8949
- if (spec.startsWith("@/")) return path61.resolve(sourceRoot, spec.slice(2));
9489
+ if (spec.startsWith("/")) return path64.resolve(spec);
9490
+ if (spec.startsWith("./") || spec.startsWith("../")) return path64.resolve(path64.dirname(fromFile), spec);
9491
+ if (spec.startsWith("@/")) return path64.resolve(sourceRoot, spec.slice(2));
8950
9492
  return void 0;
8951
9493
  }
8952
9494
  function buildStylesheetGraph(options) {
8953
9495
  const { cssFiles, sourceRoot, textOf } = options;
8954
- const cssSet = new Set(cssFiles.map((file) => path61.normalize(file)));
9496
+ const cssSet = new Set(cssFiles.map((file) => path64.normalize(file)));
8955
9497
  const globals = cssFiles.filter((file) => registersTailwind(textOf(file)));
8956
9498
  const reachable = /* @__PURE__ */ new Set();
8957
9499
  const queue = [...globals];
8958
- for (const global of globals) reachable.add(path61.normalize(global));
9500
+ for (const global of globals) reachable.add(path64.normalize(global));
8959
9501
  while (queue.length > 0) {
8960
9502
  const from = queue.shift();
8961
9503
  if (!from) continue;
8962
9504
  for (const spec of importedSpecifiers(textOf(from))) {
8963
9505
  const target = resolveSpecifier2(from, spec, sourceRoot);
8964
9506
  if (!target) continue;
8965
- const normalized = path61.normalize(target);
9507
+ const normalized = path64.normalize(target);
8966
9508
  if (cssSet.has(normalized) && !reachable.has(normalized)) {
8967
9509
  reachable.add(normalized);
8968
9510
  queue.push(normalized);
@@ -8974,7 +9516,7 @@ function buildStylesheetGraph(options) {
8974
9516
  for (const spec of importedSpecifiers(textOf(global))) {
8975
9517
  const target = resolveSpecifier2(global, spec, sourceRoot);
8976
9518
  if (!target) continue;
8977
- const normalized = path61.normalize(target);
9519
+ const normalized = path64.normalize(target);
8978
9520
  if (cssSet.has(normalized)) directChildren.add(normalized);
8979
9521
  }
8980
9522
  }
@@ -8982,8 +9524,8 @@ function buildStylesheetGraph(options) {
8982
9524
  }
8983
9525
 
8984
9526
  // eslint/rules/tailwind/css-entry-point.ts
8985
- var APP_STYLES_DIR = path62.join("app", "styles");
8986
- var GLOBAL_STYLESHEET_PATH = path62.join(APP_STYLES_DIR, "globals.css");
9527
+ var APP_STYLES_DIR = path65.join("app", "styles");
9528
+ var GLOBAL_STYLESHEET_PATH = path65.join(APP_STYLES_DIR, "globals.css");
8987
9529
  var cssEntryPointRule = {
8988
9530
  meta: {
8989
9531
  schema: [],
@@ -9009,8 +9551,8 @@ var cssEntryPointRule = {
9009
9551
  return {
9010
9552
  "StyleSheet:exit"(node) {
9011
9553
  if (globals.length === 0) return;
9012
- const current = path62.normalize(path62.resolve(context.filename));
9013
- const relative = path62.relative(sourceRoot, current);
9554
+ const current = path65.normalize(path65.resolve(context.filename));
9555
+ const relative = path65.relative(sourceRoot, current);
9014
9556
  if (globals.includes(current)) {
9015
9557
  if (globals.length > 1) {
9016
9558
  context.report({
@@ -9026,7 +9568,7 @@ var cssEntryPointRule = {
9026
9568
  });
9027
9569
  return;
9028
9570
  }
9029
- const basename = path62.basename(current);
9571
+ const basename = path65.basename(current);
9030
9572
  const importCount = moduleFiles.filter((modulePath) => moduleImports(textOf(modulePath), basename)).length;
9031
9573
  if (importCount !== 1) {
9032
9574
  context.report({
@@ -9036,7 +9578,7 @@ var cssEntryPointRule = {
9036
9578
  }
9037
9579
  return;
9038
9580
  }
9039
- const isInAppStyles = relative === APP_STYLES_DIR || relative.startsWith(`${APP_STYLES_DIR}${path62.sep}`);
9581
+ const isInAppStyles = relative === APP_STYLES_DIR || relative.startsWith(`${APP_STYLES_DIR}${path65.sep}`);
9040
9582
  if (!isInAppStyles) {
9041
9583
  context.report({
9042
9584
  node,
@@ -9525,7 +10067,7 @@ var tailwindRules = {
9525
10067
  };
9526
10068
 
9527
10069
  // eslint/rules/type-extraction.ts
9528
- import path63 from "path";
10070
+ import path66 from "path";
9529
10071
  var typeExtractionRule = {
9530
10072
  meta: {
9531
10073
  schema: [],
@@ -9536,7 +10078,7 @@ var typeExtractionRule = {
9536
10078
  },
9537
10079
  create(context) {
9538
10080
  const sourceRoot = sourceRootOf(context);
9539
- const file = path63.resolve(context.filename);
10081
+ const file = path66.resolve(context.filename);
9540
10082
  const segments = segmentsOf(file, sourceRoot);
9541
10083
  if (segments.length === 0) return {};
9542
10084
  const index = getProjectIndex(sourceRoot);
@@ -9675,9 +10217,9 @@ var uiStateRule = {
9675
10217
  };
9676
10218
 
9677
10219
  // eslint/rules/unknown-utility.ts
9678
- import { existsSync as existsSync6, readdirSync as readdirSync4, readFileSync as readFileSync12, statSync as statSync6 } from "fs";
10220
+ import { existsSync as existsSync8, readdirSync as readdirSync6, readFileSync as readFileSync14, statSync as statSync6 } from "fs";
9679
10221
  import { createRequire } from "module";
9680
- import path64 from "path";
10222
+ import path67 from "path";
9681
10223
  var PREFIX_NAMESPACES = {
9682
10224
  bg: ["color"],
9683
10225
  text: ["color", "text"],
@@ -9911,13 +10453,13 @@ function isBuiltInTailwindUtility(utility) {
9911
10453
  function stylesheetFiles(dir) {
9912
10454
  let entries;
9913
10455
  try {
9914
- entries = readdirSync4(dir);
10456
+ entries = readdirSync6(dir);
9915
10457
  } catch {
9916
10458
  return [];
9917
10459
  }
9918
10460
  return entries.flatMap((entry) => {
9919
10461
  if (entry.startsWith(".") || entry === "node_modules") return [];
9920
- const entryPath = path64.join(dir, entry);
10462
+ const entryPath = path67.join(dir, entry);
9921
10463
  let stats;
9922
10464
  try {
9923
10465
  stats = statSync6(entryPath);
@@ -9925,7 +10467,7 @@ function stylesheetFiles(dir) {
9925
10467
  return [];
9926
10468
  }
9927
10469
  if (stats.isDirectory()) return stylesheetFiles(entryPath);
9928
- return path64.extname(entry) === ".css" ? [entryPath] : [];
10470
+ return path67.extname(entry) === ".css" ? [entryPath] : [];
9929
10471
  });
9930
10472
  }
9931
10473
  function packageNameOf(specifier) {
@@ -9936,24 +10478,24 @@ function packageNameOf(specifier) {
9936
10478
  function resolvePackageStylesheet(fromFile, specifier) {
9937
10479
  const packageName = packageNameOf(specifier);
9938
10480
  if (!packageName || packageName === "tailwindcss") return void 0;
9939
- let directory = path64.dirname(fromFile);
9940
- while (directory !== path64.dirname(directory)) {
9941
- const packageRoot = path64.join(directory, "node_modules", packageName);
9942
- const manifestPath = path64.join(packageRoot, "package.json");
9943
- if (existsSync6(manifestPath)) {
10481
+ let directory = path67.dirname(fromFile);
10482
+ while (directory !== path67.dirname(directory)) {
10483
+ const packageRoot = path67.join(directory, "node_modules", packageName);
10484
+ const manifestPath = path67.join(packageRoot, "package.json");
10485
+ if (existsSync8(manifestPath)) {
9944
10486
  try {
9945
- const manifest = readFileSync12(manifestPath, "utf8");
10487
+ const manifest = readFileSync14(manifestPath, "utf8");
9946
10488
  const stylesheet = /"style"\s*:\s*"(?<file>[^"]+\.css)"/.exec(manifest)?.groups?.file;
9947
10489
  const main = /"main"\s*:\s*"(?<file>[^"]+\.css)"/.exec(manifest)?.groups?.file;
9948
10490
  const target = stylesheet ?? main;
9949
10491
  if (!target) return void 0;
9950
- const resolved = path64.resolve(packageRoot, target);
9951
- return existsSync6(resolved) ? resolved : void 0;
10492
+ const resolved = path67.resolve(packageRoot, target);
10493
+ return existsSync8(resolved) ? resolved : void 0;
9952
10494
  } catch {
9953
10495
  return void 0;
9954
10496
  }
9955
10497
  }
9956
- directory = path64.dirname(directory);
10498
+ directory = path67.dirname(directory);
9957
10499
  }
9958
10500
  return void 0;
9959
10501
  }
@@ -9962,7 +10504,7 @@ function inventoryStylesheetFiles(projectFiles) {
9962
10504
  for (const file of projectFiles) {
9963
10505
  let css2;
9964
10506
  try {
9965
- css2 = readFileSync12(file, "utf8");
10507
+ css2 = readFileSync14(file, "utf8");
9966
10508
  } catch {
9967
10509
  continue;
9968
10510
  }
@@ -10028,7 +10570,7 @@ function readInventory(files) {
10028
10570
  for (const file of files) {
10029
10571
  let css2;
10030
10572
  try {
10031
- css2 = readFileSync12(file, "utf8");
10573
+ css2 = readFileSync14(file, "utf8");
10032
10574
  } catch {
10033
10575
  continue;
10034
10576
  }
@@ -10204,7 +10746,7 @@ var unknownUtilityRule = {
10204
10746
  };
10205
10747
 
10206
10748
  // eslint/rules/util-file-name.ts
10207
- import path65 from "path";
10749
+ import path68 from "path";
10208
10750
  function toKebabCase2(value) {
10209
10751
  return value.replace(/(?<lower>[a-z0-9])(?<upper>[A-Z])/g, "$<lower>-$<upper>").replace(/(?<first>[A-Z])(?<rest>[A-Z][a-z])/g, "$<first>-$<rest>").toLowerCase();
10210
10752
  }
@@ -10217,7 +10759,7 @@ var utilFileNameRule = {
10217
10759
  }
10218
10760
  },
10219
10761
  create(context) {
10220
- const filename = path65.resolve(context.filename);
10762
+ const filename = path68.resolve(context.filename);
10221
10763
  const segments = filename.replace(/\\/g, "/").split("/");
10222
10764
  if (!segments.includes("utils")) return {};
10223
10765
  let module;
@@ -10231,13 +10773,13 @@ var utilFileNameRule = {
10231
10773
  const functionName = functions[0]?.name;
10232
10774
  if (!functionName) return {};
10233
10775
  const expected = toKebabCase2(functionName);
10234
- const actual = path65.basename(filename, path65.extname(filename));
10776
+ const actual = path68.basename(filename, path68.extname(filename));
10235
10777
  if (!expected || actual === expected) return {};
10236
10778
  return {
10237
10779
  Program(node) {
10238
10780
  context.report({
10239
10781
  node,
10240
- message: `A utility file exporting ${functionName} must be named ${expected}.${path65.extname(filename).slice(1)}.`
10782
+ message: `A utility file exporting ${functionName} must be named ${expected}.${path68.extname(filename).slice(1)}.`
10241
10783
  });
10242
10784
  }
10243
10785
  };
@@ -10245,7 +10787,7 @@ var utilFileNameRule = {
10245
10787
  };
10246
10788
 
10247
10789
  // eslint/rules/value-extraction.ts
10248
- import path66 from "path";
10790
+ import path69 from "path";
10249
10791
  var valueExtractionRule = {
10250
10792
  meta: {
10251
10793
  schema: [],
@@ -10256,7 +10798,7 @@ var valueExtractionRule = {
10256
10798
  },
10257
10799
  create(context) {
10258
10800
  const sourceRoot = sourceRootOf(context);
10259
- const file = path66.resolve(context.filename);
10801
+ const file = path69.resolve(context.filename);
10260
10802
  const segments = segmentsOf(file, sourceRoot);
10261
10803
  if (segments.length === 0 || segments[0] !== "app") return {};
10262
10804
  const index = getProjectIndex(sourceRoot);
@@ -10277,8 +10819,8 @@ var valueExtractionRule = {
10277
10819
  };
10278
10820
 
10279
10821
  // eslint/rules/vulyk/tracked-docs.ts
10280
- import { existsSync as existsSync7, readFileSync as readFileSync13 } from "fs";
10281
- import path67 from "path";
10822
+ import { existsSync as existsSync9, readFileSync as readFileSync15 } from "fs";
10823
+ import path70 from "path";
10282
10824
  var PASIKA_REPO = "Bredansky/pasika";
10283
10825
  var BASE_REQUIRED_TRACKED_DOCS = [
10284
10826
  { name: "documentation-guide", path: "docs/documentation-guide" },
@@ -10289,13 +10831,13 @@ var NEXTJS_REQUIRED_TRACKED_DOCS = [
10289
10831
  { name: "next-codebase-guide", path: "docs/next-codebase-guide" },
10290
10832
  { name: "next-tailwind-guide", path: "docs/next-tailwind-guide" }
10291
10833
  ];
10292
- function memberName7(member) {
10834
+ function memberName8(member) {
10293
10835
  return member.name.type === "String" ? member.name.value : member.name.name;
10294
10836
  }
10295
10837
  function hasDependency(root, name) {
10296
- const section = root.members.find((member) => memberName7(member) === "dependencies");
10838
+ const section = root.members.find((member) => memberName8(member) === "dependencies");
10297
10839
  if (section?.value.type !== "Object") return false;
10298
- return section.value.members.some((member) => memberName7(member) === name);
10840
+ return section.value.members.some((member) => memberName8(member) === name);
10299
10841
  }
10300
10842
  var trackedDocsRule = {
10301
10843
  meta: {
@@ -10311,16 +10853,16 @@ var trackedDocsRule = {
10311
10853
  if (!context.filename.endsWith("package.json")) return;
10312
10854
  const root = node.body;
10313
10855
  if (root.type !== "Object") return;
10314
- const projectRoot = path67.dirname(path67.resolve(context.filename));
10315
- const configPath = path67.join(projectRoot, "vulyk.config.ts");
10316
- if (!existsSync7(configPath)) {
10856
+ const projectRoot = path70.dirname(path70.resolve(context.filename));
10857
+ const configPath = path70.join(projectRoot, "vulyk.config.ts");
10858
+ if (!existsSync9(configPath)) {
10317
10859
  context.report({
10318
10860
  node,
10319
10861
  message: "No vulyk.config.ts found. Run npx vulyk init to create one that tracks the framework's required tracked docs."
10320
10862
  });
10321
10863
  return;
10322
10864
  }
10323
- const config = readFileSync13(configPath, "utf8");
10865
+ const config = readFileSync15(configPath, "utf8");
10324
10866
  if (!config.includes(PASIKA_REPO)) {
10325
10867
  context.report({
10326
10868
  node,
@@ -10337,8 +10879,8 @@ var trackedDocsRule = {
10337
10879
  });
10338
10880
  }
10339
10881
  }
10340
- const agentsPath = path67.join(projectRoot, "AGENTS.md");
10341
- if (!existsSync7(agentsPath)) {
10882
+ const agentsPath = path70.join(projectRoot, "AGENTS.md");
10883
+ if (!existsSync9(agentsPath)) {
10342
10884
  context.report({
10343
10885
  node,
10344
10886
  message: "No AGENTS.md found. Run npx vulyk agents to generate the agent file that routes to the tracked docs."
@@ -10350,14 +10892,14 @@ var trackedDocsRule = {
10350
10892
  };
10351
10893
 
10352
10894
  // eslint/rules/vulyk/vulyk-dependency.ts
10353
- function memberName8(member) {
10895
+ function memberName9(member) {
10354
10896
  return member.name.type === "String" ? member.name.value : member.name.name;
10355
10897
  }
10356
10898
  function dependency(root, sectionName) {
10357
10899
  if (root.type !== "Object") return void 0;
10358
- const section = root.members.find((member) => memberName8(member) === sectionName);
10900
+ const section = root.members.find((member) => memberName9(member) === sectionName);
10359
10901
  if (section?.value.type !== "Object") return void 0;
10360
- return section.value.members.find((member) => memberName8(member) === "vulyk");
10902
+ return section.value.members.find((member) => memberName9(member) === "vulyk");
10361
10903
  }
10362
10904
  var vulykDependencyRule = {
10363
10905
  meta: {
@@ -10398,9 +10940,9 @@ var vulykRules = {
10398
10940
  // eslint/rules/with-response-helper.ts
10399
10941
  var HELPER3 = "withResponse";
10400
10942
  var ENTRY3 = "pasika/with-response";
10401
- var DOC8 = "docs/pasika-adoption-guide/rules/with-response-helper-rule.md";
10402
- var DECLARED3 = `A repository must not declare its own ${HELPER3}; import it from ${ENTRY3}. See ${DOC8}`;
10403
- var IMPORTED3 = `${HELPER3} must be imported from ${ENTRY3}. See ${DOC8}`;
10943
+ var DOC9 = "docs/pasika-adoption-guide/rules/with-response-helper-rule.md";
10944
+ var DECLARED3 = `A repository must not declare its own ${HELPER3}; import it from ${ENTRY3}. See ${DOC9}`;
10945
+ var IMPORTED3 = `${HELPER3} must be imported from ${ENTRY3}. See ${DOC9}`;
10404
10946
  function isNamed3(node, name) {
10405
10947
  return node?.type === "Identifier" && node.name === name;
10406
10948
  }
@@ -10437,7 +10979,7 @@ var withResponseHelperRule = {
10437
10979
 
10438
10980
  // eslint/rules/zirka-baseline.ts
10439
10981
  import fs7 from "fs";
10440
- import path68 from "path";
10982
+ import path71 from "path";
10441
10983
  var ESLINT_CONFIG = /^eslint\.config\.(?:ts|mts|cts|js|mjs|cjs)$/;
10442
10984
  var PRETTIER_CONFIGS = [
10443
10985
  "prettier.config.mjs",
@@ -10456,10 +10998,10 @@ var zirkaBaselineRule = {
10456
10998
  }
10457
10999
  },
10458
11000
  create(context) {
10459
- const filename = path68.resolve(context.filename);
10460
- const basename = path68.basename(filename);
11001
+ const filename = path71.resolve(context.filename);
11002
+ const basename = path71.basename(filename);
10461
11003
  if (!ESLINT_CONFIG.test(basename)) return {};
10462
- const projectRoot = path68.dirname(filename);
11004
+ const projectRoot = path71.dirname(filename);
10463
11005
  const report3 = (message) => {
10464
11006
  context.report({
10465
11007
  node: context.sourceCode.ast,
@@ -10474,7 +11016,7 @@ var zirkaBaselineRule = {
10474
11016
  'ESLint config must take its configuration from zirka (import { styleguide } from "zirka") instead of restating rules locally.'
10475
11017
  );
10476
11018
  }
10477
- const tsconfigPath = path68.join(projectRoot, "tsconfig.json");
11019
+ const tsconfigPath = path71.join(projectRoot, "tsconfig.json");
10478
11020
  if (!fs7.existsSync(tsconfigPath)) {
10479
11021
  report3('No tsconfig.json found. Create one extending the zirka TypeScript base config ("zirka/typescript").');
10480
11022
  } else {
@@ -10492,13 +11034,13 @@ var zirkaBaselineRule = {
10492
11034
  report3('tsconfig.json must extend the zirka TypeScript base config ("zirka/typescript").');
10493
11035
  }
10494
11036
  }
10495
- const prettierConfigFile = PRETTIER_CONFIGS.find((name) => fs7.existsSync(path68.join(projectRoot, name)));
11037
+ const prettierConfigFile = PRETTIER_CONFIGS.find((name) => fs7.existsSync(path71.join(projectRoot, name)));
10496
11038
  if (!prettierConfigFile) {
10497
11039
  report3(
10498
11040
  "No prettier config found. Create one that takes its configuration from zirka (styleguide({ prettier: true }).prettierConfig)."
10499
11041
  );
10500
11042
  } else {
10501
- const content = fs7.readFileSync(path68.join(projectRoot, prettierConfigFile), "utf8");
11043
+ const content = fs7.readFileSync(path71.join(projectRoot, prettierConfigFile), "utf8");
10502
11044
  if (!content.includes("zirka")) {
10503
11045
  report3(
10504
11046
  "The prettier config must take its configuration from zirka (styleguide({ prettier: true }).prettierConfig) instead of restating it locally."
@@ -10521,10 +11063,10 @@ function referencesZirka(sourceCode) {
10521
11063
  // eslint/rules/zod-fetch-helper.ts
10522
11064
  var HELPER4 = "zodFetch";
10523
11065
  var ENTRY4 = "pasika/zod-fetch";
10524
- var DOC9 = "docs/pasika-adoption-guide/rules/zod-fetch-helper-rule.md";
10525
- var FETCHED = `fetch must not be called; make the request through ${HELPER4} from ${ENTRY4}. See ${DOC9}`;
10526
- var DECLARED4 = `A file must not declare its own ${HELPER4}; import it from ${ENTRY4}. See ${DOC9}`;
10527
- var IMPORTED4 = `${HELPER4} must be imported from ${ENTRY4}. See ${DOC9}`;
11066
+ var DOC10 = "docs/pasika-adoption-guide/rules/zod-fetch-helper-rule.md";
11067
+ var FETCHED = `fetch must not be called; make the request through ${HELPER4} from ${ENTRY4}. See ${DOC10}`;
11068
+ var DECLARED4 = `A file must not declare its own ${HELPER4}; import it from ${ENTRY4}. See ${DOC10}`;
11069
+ var IMPORTED4 = `${HELPER4} must be imported from ${ENTRY4}. See ${DOC10}`;
10528
11070
  var GLOBAL_OBJECTS = /* @__PURE__ */ new Set(["globalThis", "window", "self", "global"]);
10529
11071
  var TEST_FILE2 = /(?:^|[\\/])(?:__tests__|tests)[\\/]|[.](?:test|spec)[.][cm]?[jt]sx?$/;
10530
11072
  function isNamed4(node, name) {
@@ -10644,14 +11186,14 @@ var zodSchemaValidationRule = {
10644
11186
  };
10645
11187
 
10646
11188
  // eslint/ts-alignment.ts
10647
- import { readFileSync as readFileSync14 } from "fs";
11189
+ import { readFileSync as readFileSync16 } from "fs";
10648
11190
  import { createRequire as createRequire2 } from "module";
10649
11191
  import { join } from "path";
10650
11192
  var ownRequire = createRequire2(import.meta.url);
10651
11193
  var majorOf = (version) => Number(version.split(".")[0]);
10652
11194
  function versionOf(packagePath) {
10653
11195
  try {
10654
- const parsed = JSON.parse(readFileSync14(packagePath, "utf8"));
11196
+ const parsed = JSON.parse(readFileSync16(packagePath, "utf8"));
10655
11197
  if (typeof parsed !== "object" || parsed === null || !("version" in parsed)) return null;
10656
11198
  return typeof parsed.version === "string" ? parsed.version : null;
10657
11199
  } catch {