pasika 0.10.55 → 0.10.57

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.
@@ -4,17 +4,170 @@ import jsonPlugin from "@eslint/json";
4
4
  import markdown from "@eslint/markdown";
5
5
  import tsParser from "@typescript-eslint/parser";
6
6
 
7
+ // eslint/rules/api-contract.ts
8
+ import path from "path";
9
+ var HELPER = "defineApiContract";
10
+ var ENTRY = "pasika/api-contract";
11
+ var DOC = "docs/pasika-adoption-guide/rules/api-contract-rule.md";
12
+ var TEST_FILE = /(?:^|[\\/])(?:__tests__|tests)[\\/]|[.](?:test|spec)[.][cm]?[jt]sx?$/;
13
+ var DECLARED = `A repository must not declare its own ${HELPER}; import it from ${ENTRY}. See ${DOC}`;
14
+ var IMPORTED = `${HELPER} must be imported from ${ENTRY}. See ${DOC}`;
15
+ var EXPORTED = `A call to ${HELPER} must initialize an exported named contract. See ${DOC}`;
16
+ var DEFINED = `An exported *ApiContract value must be created with ${HELPER}. See ${DOC}`;
17
+ var ROUTE_IMPORTED = `withResponse must receive an imported API contract for a JSON route. See ${DOC}`;
18
+ var CLIENT_CONTRACT = `A schema-validated request must use an imported API contract through zodFetch({ contract }). See ${DOC}`;
19
+ var MOCK_PATH = `A mock apiRoutePath must come from an imported API contract through contract.path. See ${DOC}`;
20
+ var MOCK_RESPONSE = `A mock must validate successful JSON with the same API contract responseSchema. See ${DOC}`;
21
+ function isNamed(node, name) {
22
+ return node?.type === "Identifier" && node.name === name;
23
+ }
24
+ function importedBindings(program) {
25
+ const names = /* @__PURE__ */ new Set();
26
+ for (const statement of program.body) {
27
+ if (statement.type !== "ImportDeclaration") continue;
28
+ for (const specifier of statement.specifiers) {
29
+ names.add(specifier.local.name);
30
+ }
31
+ }
32
+ return names;
33
+ }
34
+ function memberPropertyName(node) {
35
+ if (!node.computed && node.property.type === "Identifier") return node.property.name;
36
+ if (node.computed && node.property.type === "Literal" && typeof node.property.value === "string") {
37
+ return node.property.value;
38
+ }
39
+ return void 0;
40
+ }
41
+ function importedContractMember(expression, propertyName3, imports) {
42
+ if (expression?.type !== "MemberExpression" || memberPropertyName(expression) !== propertyName3 || expression.object.type !== "Identifier" || !imports.has(expression.object.name)) {
43
+ return void 0;
44
+ }
45
+ return expression.object.name;
46
+ }
47
+ function responseSchemaParserContract(callee, imports) {
48
+ if (callee.type === "Super" || callee.type !== "MemberExpression" || memberPropertyName(callee) !== "parse") {
49
+ return void 0;
50
+ }
51
+ if (callee.object.type !== "MemberExpression" || memberPropertyName(callee.object) !== "responseSchema") {
52
+ return void 0;
53
+ }
54
+ if (callee.object.object.type !== "Identifier" || !imports.has(callee.object.object.name)) return void 0;
55
+ return callee.object.object.name;
56
+ }
57
+ function objectProperty(object, name) {
58
+ return object.properties.find(
59
+ (property) => property.type === "Property" && !property.computed && (property.key.type === "Identifier" && property.key.name === name || property.key.type === "Literal" && property.key.value === name)
60
+ );
61
+ }
62
+ function isExportedVariable(context, node) {
63
+ const ancestors = context.sourceCode.getAncestors(node);
64
+ return ancestors.at(-2)?.type === "ExportNamedDeclaration";
65
+ }
66
+ function isExportedDefinition(context, node) {
67
+ const ancestors = context.sourceCode.getAncestors(node);
68
+ const declarator = ancestors.at(-1);
69
+ const declaration = ancestors.at(-2);
70
+ const exported = ancestors.at(-3);
71
+ return declarator?.type === "VariableDeclarator" && declarator.init === node && declarator.id.type === "Identifier" && declaration?.type === "VariableDeclaration" && exported?.type === "ExportNamedDeclaration";
72
+ }
73
+ var apiContractRule = {
74
+ meta: {
75
+ schema: [],
76
+ type: "problem",
77
+ docs: {
78
+ description: "Require schema-validated JSON routes and clients to reuse one exported API contract instead of restating schemas."
79
+ }
80
+ },
81
+ create(context) {
82
+ if (TEST_FILE.test(context.filename)) return {};
83
+ const imports = importedBindings(context.sourceCode.ast);
84
+ let mockContract;
85
+ const mockResponseContracts = /* @__PURE__ */ new Set();
86
+ return {
87
+ ImportDeclaration(node) {
88
+ if (node.source.value === ENTRY) return;
89
+ for (const specifier of node.specifiers) {
90
+ if (isNamed(specifier.local, HELPER)) {
91
+ context.report({ node: specifier, message: IMPORTED });
92
+ }
93
+ }
94
+ },
95
+ FunctionDeclaration(node) {
96
+ if (isNamed(node.id, HELPER)) context.report({ node, message: DECLARED });
97
+ },
98
+ VariableDeclarator(node) {
99
+ if (node.id.type !== "Identifier") return;
100
+ if (node.id.name === HELPER) {
101
+ context.report({ node, message: DECLARED });
102
+ return;
103
+ }
104
+ if (node.id.name.endsWith("ApiContract") && isExportedVariable(context, node)) {
105
+ const isFactoryCall = node.init?.type === "CallExpression" && isNamed(node.init.callee, HELPER);
106
+ if (!isFactoryCall) {
107
+ context.report({ node, message: DEFINED });
108
+ return;
109
+ }
110
+ }
111
+ if (node.id.name !== "apiRoutePath") return;
112
+ const contractName = importedContractMember(node.init, "path", imports);
113
+ if (!contractName) {
114
+ context.report({ node, message: MOCK_PATH });
115
+ return;
116
+ }
117
+ mockContract = { name: contractName, node };
118
+ },
119
+ CallExpression(node) {
120
+ const responseContract = responseSchemaParserContract(node.callee, imports);
121
+ if (responseContract) mockResponseContracts.add(responseContract);
122
+ if (isNamed(node.callee, HELPER) && !isExportedDefinition(context, node)) {
123
+ context.report({ node, message: EXPORTED });
124
+ return;
125
+ }
126
+ if (isNamed(node.callee, "withResponse") && path.basename(context.filename) === "route.ts") {
127
+ const contract = node.arguments[0];
128
+ if (contract && contract.type !== "SpreadElement" && contract.type !== "ArrowFunctionExpression" && contract.type !== "FunctionExpression" && (contract.type !== "Identifier" || !imports.has(contract.name))) {
129
+ context.report({ node: contract, message: ROUTE_IMPORTED });
130
+ }
131
+ return;
132
+ }
133
+ if (!isNamed(node.callee, "zodFetch")) return;
134
+ const options = node.arguments[0];
135
+ if (options?.type !== "ObjectExpression") return;
136
+ const contractProperty = objectProperty(options, "contract");
137
+ if (contractProperty) {
138
+ const value = contractProperty.value;
139
+ if (!(value.type === "Identifier" && imports.has(value.name))) {
140
+ context.report({ node: value, message: CLIENT_CONTRACT });
141
+ }
142
+ return;
143
+ }
144
+ const responseSchemaProperty = objectProperty(options, "responseSchema");
145
+ const requestSchemaProperty = objectProperty(options, "requestSchema");
146
+ const schemaProperty = responseSchemaProperty ?? requestSchemaProperty;
147
+ if (schemaProperty) {
148
+ context.report({ node: schemaProperty, message: CLIENT_CONTRACT });
149
+ }
150
+ },
151
+ "Program:exit"() {
152
+ if (mockContract && !mockResponseContracts.has(mockContract.name)) {
153
+ context.report({ node: mockContract.node, message: MOCK_RESPONSE });
154
+ }
155
+ }
156
+ };
157
+ }
158
+ };
159
+
7
160
  // eslint/rules/application-structure.ts
8
161
  import fs2 from "fs";
9
- import path4 from "path";
162
+ import path5 from "path";
10
163
 
11
164
  // eslint/project/ccf.ts
12
165
  import fs from "fs";
13
- import path from "path";
166
+ import path2 from "path";
14
167
  var SUPPORT_FOLDERS = /* @__PURE__ */ new Set(["hooks", "types", "schemas", "constants", "utils"]);
15
168
  function segmentsOf(file, sourceRoot) {
16
- const relative = path.relative(sourceRoot, file);
17
- return relative.startsWith("..") ? [] : relative.split(path.sep);
169
+ const relative = path2.relative(sourceRoot, file);
170
+ return relative.startsWith("..") ? [] : relative.split(path2.sep);
18
171
  }
19
172
  function folderSegmentsOf(file, sourceRoot) {
20
173
  return segmentsOf(file, sourceRoot).slice(0, -1);
@@ -77,7 +230,7 @@ function hasComponentOwner(folderPath, folderName) {
77
230
  function isValidComponentFolder(folder, sourceRoot) {
78
231
  const name = folder[folder.length - 1];
79
232
  if (!name || SUPPORT_FOLDERS.has(name)) return false;
80
- const folderPath = path.join(sourceRoot, ...folder);
233
+ const folderPath = path2.join(sourceRoot, ...folder);
81
234
  return hasComponentOwner(folderPath, name) && hasExactEntry(folderPath, "index.ts");
82
235
  }
83
236
  function owningFolderOf(consumer, sourceRoot) {
@@ -114,14 +267,14 @@ function resolveSupportPlacement(supportFile, supportFolder, index, importedBy =
114
267
  }
115
268
  function describeConsumers(consumers, sourceRoot) {
116
269
  const shown = 3;
117
- const names = consumers.map((consumer) => path.relative(path.dirname(sourceRoot), consumer).split(path.sep).join("/")).sort((left, right) => left.localeCompare(right));
270
+ const names = consumers.map((consumer) => path2.relative(path2.dirname(sourceRoot), consumer).split(path2.sep).join("/")).sort((left, right) => left.localeCompare(right));
118
271
  if (names.length <= shown) return names.join(", ");
119
272
  return `${names.slice(0, shown).join(", ")} and ${String(names.length - shown)} more`;
120
273
  }
121
274
 
122
275
  // eslint/project/parse-module.ts
123
276
  import { readFileSync } from "fs";
124
- import path2 from "path";
277
+ import path3 from "path";
125
278
  import ts from "typescript";
126
279
  var isPascalCase = (name) => /^[A-Z][A-Za-z0-9]*$/.test(name);
127
280
  var isHookName = (name) => /^use[A-Z]/.test(name);
@@ -245,13 +398,13 @@ function parseModule(file) {
245
398
  });
246
399
  }
247
400
  }
248
- return { file: path2.resolve(file), imports, reexports, exports };
401
+ return { file: path3.resolve(file), imports, reexports, exports };
249
402
  }
250
403
 
251
404
  // eslint/rules/project-root.ts
252
- import path3 from "path";
405
+ import path4 from "path";
253
406
  function sourceRootOf(context) {
254
- return path3.resolve(context.cwd ?? process.cwd(), "src");
407
+ return path4.resolve(context.cwd ?? process.cwd(), "src");
255
408
  }
256
409
 
257
410
  // eslint/rules/application-structure.ts
@@ -292,7 +445,7 @@ function report(context, message) {
292
445
  };
293
446
  }
294
447
  function isCodeFile(filename) {
295
- return MODULE_EXTENSIONS.has(path4.extname(filename));
448
+ return MODULE_EXTENSIONS.has(path5.extname(filename));
296
449
  }
297
450
  function isRootSupportFolder(folder) {
298
451
  return SUPPORT_FOLDERS.has(folder);
@@ -319,7 +472,7 @@ function mixedSupportKinds(folder, kinds) {
319
472
  function configModuleRoot(filename, sourceRoot) {
320
473
  const segments = segmentsOf(filename, sourceRoot);
321
474
  if (segments[0] !== "config" || segments.length < 3) return void 0;
322
- return path4.join(sourceRoot, "config", segments[1] ?? "");
475
+ return path5.join(sourceRoot, "config", segments[1] ?? "");
323
476
  }
324
477
  function componentFolderStart(segments) {
325
478
  if (segments[0] === "features") return 2;
@@ -335,7 +488,7 @@ function componentFolderViolation(segments, sourceRoot) {
335
488
  for (let depth = segments.length - 2; depth >= start; depth -= 1) {
336
489
  const folder = segments[depth];
337
490
  if (!folder || SUPPORT_FOLDERS.has(folder)) continue;
338
- const folderPath = path4.join(sourceRoot, ...segments.slice(0, depth + 1));
491
+ const folderPath = path5.join(sourceRoot, ...segments.slice(0, depth + 1));
339
492
  const label = `src/${segments.slice(0, depth + 1).join("/")}/`;
340
493
  if (!hasComponentOwner(folderPath, folder)) {
341
494
  return `A folder that is not a support folder must be a component folder; add "${folder}.tsx" to ${label} or move its files into a support folder.`;
@@ -355,7 +508,7 @@ var applicationStructureRule = {
355
508
  }
356
509
  },
357
510
  create(context) {
358
- const filename = path4.resolve(context.filename);
511
+ const filename = path5.resolve(context.filename);
359
512
  const sourceRoot = sourceRootOf(context);
360
513
  const segments = segmentsOf(filename, sourceRoot);
361
514
  if (segments.length === 0) return {};
@@ -386,43 +539,43 @@ var applicationStructureRule = {
386
539
  );
387
540
  }
388
541
  const moduleRoot = configModuleRoot(filename, sourceRoot);
389
- if (moduleRoot && !fs2.existsSync(path4.join(moduleRoot, "index.ts"))) {
542
+ if (moduleRoot && !fs2.existsSync(path5.join(moduleRoot, "index.ts"))) {
390
543
  return report(
391
544
  context,
392
- `Add src/config/${path4.basename(moduleRoot)}/index.ts as the configuration module entry point.`
545
+ `Add src/config/${path5.basename(moduleRoot)}/index.ts as the configuration module entry point.`
393
546
  );
394
547
  }
395
- if (moduleRoot && segments.length === 3 && path4.basename(filename) !== "index.ts") {
548
+ if (moduleRoot && segments.length === 3 && path5.basename(filename) !== "index.ts") {
396
549
  const kinds2 = exportedKinds(filename);
397
550
  const expected2 = expectedSupportFolder(kinds2);
398
551
  if (expected2 !== void 0) {
399
552
  return report(
400
553
  context,
401
- `Move this configuration support file into src/config/${path4.basename(moduleRoot)}/${expected2}/.`
554
+ `Move this configuration support file into src/config/${path5.basename(moduleRoot)}/${expected2}/.`
402
555
  );
403
556
  }
404
557
  }
405
558
  }
406
559
  if (topLevel === "app" && isCodeFile(filename)) {
407
- const basename = path4.basename(filename, path4.extname(filename));
408
- const currentFolder2 = path4.basename(path4.dirname(filename));
560
+ const basename = path5.basename(filename, path5.extname(filename));
561
+ const currentFolder2 = path5.basename(path5.dirname(filename));
409
562
  if (SUPPORT_FOLDERS.has(currentFolder2)) {
410
563
  return report(
411
564
  context,
412
565
  "src/app/ may contain routing files and framework assets, but ordinary components and support files must live outside src/app/."
413
566
  );
414
567
  }
415
- if (!ROUTING_FILES.has(basename) && path4.extname(filename) !== ".css") {
568
+ if (!ROUTING_FILES.has(basename) && path5.extname(filename) !== ".css") {
416
569
  return report(
417
570
  context,
418
571
  "src/app/ may contain routing files and framework assets, but ordinary components and support files must live outside src/app/."
419
572
  );
420
573
  }
421
- if (ROUTING_FILES.has(basename) || path4.extname(filename) === ".css") return {};
574
+ if (ROUTING_FILES.has(basename) || path5.extname(filename) === ".css") return {};
422
575
  }
423
- const currentFolder = path4.basename(path4.dirname(filename));
576
+ const currentFolder = path5.basename(path5.dirname(filename));
424
577
  const kinds = exportedKinds(filename);
425
- const isConfigModuleRoot = topLevel === "config" && segments.length === 3 && path4.basename(filename) === "index.ts";
578
+ const isConfigModuleRoot = topLevel === "config" && segments.length === 3 && path5.basename(filename) === "index.ts";
426
579
  if (isConfigModuleRoot) return {};
427
580
  if (!SUPPORT_FOLDERS.has(currentFolder)) {
428
581
  const expected2 = expectedSupportFolder(kinds);
@@ -439,7 +592,7 @@ var applicationStructureRule = {
439
592
  if (kinds.has("component")) {
440
593
  return report(
441
594
  context,
442
- `A support folder must not contain a component; move ${path4.basename(filename)} beside ${currentFolder}/.`
595
+ `A support folder must not contain a component; move ${path5.basename(filename)} beside ${currentFolder}/.`
443
596
  );
444
597
  }
445
598
  if (mixedSupportKinds(currentFolder, kinds)) {
@@ -462,12 +615,12 @@ var applicationStructureRule = {
462
615
  };
463
616
 
464
617
  // eslint/rules/cn-helper.ts
465
- var HELPER = "cn";
466
- var ENTRY = "pasika/cn";
467
- var DOC = "docs/pasika-adoption-guide/rules/cn-helper-rule.md";
468
- var DECLARED = `A file must not declare its own ${HELPER}; import it from ${ENTRY}. See ${DOC}`;
469
- var IMPORTED = `${HELPER} must be imported from ${ENTRY}. See ${DOC}`;
470
- function isNamed(node, name) {
618
+ var HELPER2 = "cn";
619
+ var ENTRY2 = "pasika/cn";
620
+ var DOC2 = "docs/pasika-adoption-guide/rules/cn-helper-rule.md";
621
+ var DECLARED2 = `A file must not declare its own ${HELPER2}; import it from ${ENTRY2}. See ${DOC2}`;
622
+ var IMPORTED2 = `${HELPER2} must be imported from ${ENTRY2}. See ${DOC2}`;
623
+ function isNamed2(node, name) {
471
624
  return node?.type === "Identifier" && node.name === name;
472
625
  }
473
626
  var cnHelperRule = {
@@ -475,24 +628,24 @@ var cnHelperRule = {
475
628
  schema: [],
476
629
  type: "problem",
477
630
  docs: {
478
- description: `Require ${HELPER} to be imported from ${ENTRY} rather than declared in the repository.`
631
+ description: `Require ${HELPER2} to be imported from ${ENTRY2} rather than declared in the repository.`
479
632
  }
480
633
  },
481
634
  create(context) {
482
635
  const checkSource = (node) => {
483
- if (!node.source || node.source.value === ENTRY) return;
636
+ if (!node.source || node.source.value === ENTRY2) return;
484
637
  for (const specifier of node.specifiers) {
485
- if (!isNamed(specifier.local, HELPER)) continue;
486
- context.report({ node: specifier, message: IMPORTED });
638
+ if (!isNamed2(specifier.local, HELPER2)) continue;
639
+ context.report({ node: specifier, message: IMPORTED2 });
487
640
  }
488
641
  };
489
642
  return {
490
643
  FunctionDeclaration(node) {
491
- if (isNamed(node.id, HELPER)) context.report({ node, message: DECLARED });
644
+ if (isNamed2(node.id, HELPER2)) context.report({ node, message: DECLARED2 });
492
645
  },
493
646
  VariableDeclarator(node) {
494
- if (isNamed(node.id.type === "Identifier" ? node.id : null, HELPER)) {
495
- context.report({ node, message: DECLARED });
647
+ if (isNamed2(node.id.type === "Identifier" ? node.id : null, HELPER2)) {
648
+ context.report({ node, message: DECLARED2 });
496
649
  }
497
650
  },
498
651
  ImportDeclaration: checkSource,
@@ -502,10 +655,10 @@ var cnHelperRule = {
502
655
  };
503
656
 
504
657
  // eslint/rules/component-casing.ts
505
- import path6 from "path";
658
+ import path7 from "path";
506
659
 
507
660
  // eslint/rules/component-conventions.ts
508
- import path5 from "path";
661
+ import path6 from "path";
509
662
  import ts2 from "typescript";
510
663
  var isPascalCase2 = (name) => /^[A-Z][A-Za-z0-9]*$/.test(name);
511
664
  var isHookCallName = (name) => /^use[A-Z]/.test(name);
@@ -622,7 +775,7 @@ function componentFromVariable(node) {
622
775
  };
623
776
  }
624
777
  function parseComponentInfo(text, filename, options) {
625
- const sourceFile = ts2.createSourceFile(path5.resolve(filename), text, ts2.ScriptTarget.Latest, true, ts2.ScriptKind.TSX);
778
+ const sourceFile = ts2.createSourceFile(path6.resolve(filename), text, ts2.ScriptTarget.Latest, true, ts2.ScriptKind.TSX);
626
779
  const components = [];
627
780
  const namedExports = namedExportedLocalNames(sourceFile);
628
781
  for (const statement of sourceFile.statements) {
@@ -646,7 +799,7 @@ function parseComponentInfo(text, filename, options) {
646
799
  return components;
647
800
  }
648
801
  function findJsxReturningDeclarations(text, filename) {
649
- const sourceFile = ts2.createSourceFile(path5.resolve(filename), text, ts2.ScriptTarget.Latest, true, ts2.ScriptKind.TSX);
802
+ const sourceFile = ts2.createSourceFile(path6.resolve(filename), text, ts2.ScriptTarget.Latest, true, ts2.ScriptKind.TSX);
650
803
  const results = [];
651
804
  const record = (identifier, body) => {
652
805
  if (isHookCallName(identifier.text) || !containsJsx(body)) return;
@@ -763,10 +916,10 @@ var componentCasingRule = {
763
916
  }
764
917
  },
765
918
  create(context) {
766
- const filename = path6.resolve(context.filename);
919
+ const filename = path7.resolve(context.filename);
767
920
  const sourceRoot = sourceRootOf(context);
768
- if (!filename.startsWith(sourceRoot + path6.sep)) return {};
769
- if (path6.extname(filename) !== ".tsx") return {};
921
+ if (!filename.startsWith(sourceRoot + path7.sep)) return {};
922
+ if (path7.extname(filename) !== ".tsx") return {};
770
923
  return {
771
924
  Program(node) {
772
925
  for (const declaration of findJsxReturningDeclarations(context.sourceCode.text, filename)) {
@@ -783,11 +936,11 @@ var componentCasingRule = {
783
936
  };
784
937
 
785
938
  // eslint/rules/component-nesting.ts
786
- import path8 from "path";
939
+ import path9 from "path";
787
940
 
788
941
  // eslint/project/index.ts
789
942
  import { readdirSync, statSync } from "fs";
790
- import path7 from "path";
943
+ import path8 from "path";
791
944
  var MODULE_EXTENSIONS2 = [".ts", ".tsx", ".mts", ".cts", ".js", ".jsx", ".mjs", ".cjs"];
792
945
  var INDEX_BASENAMES = ["index.ts", "index.tsx", "index.mts", "index.cts", "index.js", "index.jsx"];
793
946
  var REVALIDATE_AFTER_MS = 2e3;
@@ -801,7 +954,7 @@ function listSourceFiles(dir) {
801
954
  }
802
955
  return entries.flatMap((entry) => {
803
956
  if (entry.startsWith(".") || entry === "node_modules") return [];
804
- const entryPath = path7.join(dir, entry);
957
+ const entryPath = path8.join(dir, entry);
805
958
  let stats;
806
959
  try {
807
960
  stats = statSync(entryPath);
@@ -809,7 +962,7 @@ function listSourceFiles(dir) {
809
962
  return [];
810
963
  }
811
964
  if (stats.isDirectory()) return listSourceFiles(entryPath);
812
- return MODULE_EXTENSIONS2.includes(path7.extname(entry)) ? [entryPath] : [];
965
+ return MODULE_EXTENSIONS2.includes(path8.extname(entry)) ? [entryPath] : [];
813
966
  });
814
967
  }
815
968
  function fingerprint(files) {
@@ -825,16 +978,16 @@ function fingerprint(files) {
825
978
  function resolveSpecifier(fromFile, specifier, sourceRoot) {
826
979
  let base;
827
980
  if (specifier.startsWith("@/")) {
828
- base = path7.resolve(sourceRoot, specifier.slice(2));
981
+ base = path8.resolve(sourceRoot, specifier.slice(2));
829
982
  } else if (specifier.startsWith(".")) {
830
- base = path7.resolve(path7.dirname(fromFile), specifier);
983
+ base = path8.resolve(path8.dirname(fromFile), specifier);
831
984
  } else {
832
985
  return void 0;
833
986
  }
834
987
  const candidates = [
835
988
  base,
836
989
  ...MODULE_EXTENSIONS2.map((extension) => `${base}${extension}`),
837
- ...INDEX_BASENAMES.map((name) => path7.join(base, name))
990
+ ...INDEX_BASENAMES.map((name) => path8.join(base, name))
838
991
  ];
839
992
  for (const candidate of candidates) {
840
993
  try {
@@ -926,7 +1079,7 @@ var componentNestingRule = {
926
1079
  },
927
1080
  create(context) {
928
1081
  const sourceRoot = sourceRootOf(context);
929
- const file = path8.resolve(context.filename);
1082
+ const file = path9.resolve(context.filename);
930
1083
  const segments = segmentsOf(file, sourceRoot);
931
1084
  if (segments.length !== 4 || segments[0] !== "features") return {};
932
1085
  const index = getProjectIndex(sourceRoot);
@@ -960,7 +1113,7 @@ var componentNestingRule = {
960
1113
 
961
1114
  // eslint/rules/component-placement.ts
962
1115
  import fs3 from "fs";
963
- import path9 from "path";
1116
+ import path10 from "path";
964
1117
  var REASON_TEXT = {
965
1118
  ccf: "that is the closest folder its consumers share",
966
1119
  "across-features": "its consumers span more than one feature, and no feature may import from another",
@@ -972,7 +1125,7 @@ function isNestedInside(expectedFolder, currentFolder, componentFile) {
972
1125
  if (!sameFolder(currentFolder.slice(0, -1), expectedFolder)) return false;
973
1126
  const folderName = currentFolder[currentFolder.length - 1];
974
1127
  if (!folderName) return false;
975
- return fs3.existsSync(path9.join(path9.dirname(componentFile), `${folderName}.tsx`));
1128
+ return fs3.existsSync(path10.join(path10.dirname(componentFile), `${folderName}.tsx`));
976
1129
  }
977
1130
  var componentPlacementRule = {
978
1131
  meta: {
@@ -988,7 +1141,7 @@ var componentPlacementRule = {
988
1141
  const sourceRoot = sourceRootOf(context);
989
1142
  const index = getProjectIndex(sourceRoot);
990
1143
  if (!index) return {};
991
- const componentFile = path9.resolve(filename);
1144
+ const componentFile = path10.resolve(filename);
992
1145
  const segments = segmentsOf(componentFile, sourceRoot);
993
1146
  if (segments.length === 0) return {};
994
1147
  if (isUnderApp(segments) || isConfigModule(segments)) return {};
@@ -1037,7 +1190,7 @@ var componentPlacementRule = {
1037
1190
  };
1038
1191
 
1039
1192
  // eslint/rules/config-extraction.ts
1040
- import path10 from "path";
1193
+ import path11 from "path";
1041
1194
  var configExtractionRule = {
1042
1195
  meta: {
1043
1196
  schema: [],
@@ -1048,7 +1201,7 @@ var configExtractionRule = {
1048
1201
  },
1049
1202
  create(context) {
1050
1203
  const sourceRoot = sourceRootOf(context);
1051
- const file = path10.resolve(context.filename);
1204
+ const file = path11.resolve(context.filename);
1052
1205
  const segments = segmentsOf(file, sourceRoot);
1053
1206
  if (segments.length < 3 || segments[0] !== "config") return {};
1054
1207
  if (SUPPORT_FOLDERS.has(segments[2] ?? "")) return {};
@@ -1086,7 +1239,7 @@ var configExtractionRule = {
1086
1239
  };
1087
1240
 
1088
1241
  // eslint/rules/constant-casing.ts
1089
- import path11 from "path";
1242
+ import path12 from "path";
1090
1243
  var NEXTJS_ROUTE_HANDLER_NAMES = /* @__PURE__ */ new Set(["GET", "POST", "PUT", "PATCH", "DELETE", "HEAD", "OPTIONS"]);
1091
1244
  function isScreamingSnakeCase(name) {
1092
1245
  return /^[A-Z][A-Z0-9]*(?:_[A-Z0-9]+)*$/.test(name);
@@ -1100,9 +1253,9 @@ var constantCasingRule = {
1100
1253
  }
1101
1254
  },
1102
1255
  create(context) {
1103
- const filename = path11.resolve(context.filename);
1256
+ const filename = path12.resolve(context.filename);
1104
1257
  const sourceRoot = sourceRootOf(context);
1105
- if (!filename.startsWith(sourceRoot + path11.sep)) return {};
1258
+ if (!filename.startsWith(sourceRoot + path12.sep)) return {};
1106
1259
  return {
1107
1260
  VariableDeclarator(node) {
1108
1261
  if (node.id.type !== "Identifier") return;
@@ -1124,12 +1277,12 @@ var constantCasingRule = {
1124
1277
  };
1125
1278
 
1126
1279
  // eslint/rules/cross-feature-import.ts
1127
- import path12 from "path";
1280
+ import path13 from "path";
1128
1281
  var FEATURES_SEGMENT = "features";
1129
1282
  function featureNameOf(resolvedPath, sourceRoot) {
1130
- const relative = path12.relative(sourceRoot, resolvedPath);
1283
+ const relative = path13.relative(sourceRoot, resolvedPath);
1131
1284
  if (relative.startsWith("..")) return void 0;
1132
- const segments = relative.split(path12.sep);
1285
+ const segments = relative.split(path13.sep);
1133
1286
  if (segments[0] !== FEATURES_SEGMENT || segments.length < 2) return void 0;
1134
1287
  return segments[1];
1135
1288
  }
@@ -1145,9 +1298,9 @@ var crossFeatureImportRule = {
1145
1298
  const filename = context.filename;
1146
1299
  if (!filename.endsWith(".tsx") && !filename.endsWith(".jsx")) return {};
1147
1300
  const sourceRoot = sourceRootOf(context);
1148
- const fileRelative = path12.relative(sourceRoot, filename);
1301
+ const fileRelative = path13.relative(sourceRoot, filename);
1149
1302
  if (fileRelative.startsWith("..")) return {};
1150
- const fileSegments = fileRelative.split(path12.sep);
1303
+ const fileSegments = fileRelative.split(path13.sep);
1151
1304
  const isInCompositions = fileSegments[0] === "compositions";
1152
1305
  const isInApp = fileSegments[0] === "app";
1153
1306
  const isConfig = fileSegments[0] === "config";
@@ -1162,9 +1315,9 @@ var crossFeatureImportRule = {
1162
1315
  if (typeof source.value !== "string") return;
1163
1316
  let resolved;
1164
1317
  if (source.value.startsWith("@/")) {
1165
- resolved = path12.resolve(sourceRoot, source.value.slice(2));
1318
+ resolved = path13.resolve(sourceRoot, source.value.slice(2));
1166
1319
  } else if (source.value.startsWith(".")) {
1167
- resolved = path12.resolve(path12.dirname(filename), source.value);
1320
+ resolved = path13.resolve(path13.dirname(filename), source.value);
1168
1321
  }
1169
1322
  if (!resolved) return;
1170
1323
  const feature = featureNameOf(resolved, sourceRoot);
@@ -1315,7 +1468,7 @@ var cvaBooleanVariantsRule = {
1315
1468
  };
1316
1469
 
1317
1470
  // eslint/rules/data-component-case.ts
1318
- import path13 from "path";
1471
+ import path14 from "path";
1319
1472
  var NEXT_ROUTING_FILES = /* @__PURE__ */ new Set([
1320
1473
  "default",
1321
1474
  "error",
@@ -1346,9 +1499,9 @@ var dataComponentCaseRule = {
1346
1499
  }
1347
1500
  },
1348
1501
  create(context) {
1349
- const filename = path13.resolve(context.filename);
1502
+ const filename = path14.resolve(context.filename);
1350
1503
  if (!filename.endsWith(".tsx")) return {};
1351
- const base = path13.basename(filename, path13.extname(filename));
1504
+ const base = path14.basename(filename, path14.extname(filename));
1352
1505
  if (NEXT_ROUTING_FILES.has(base)) return {};
1353
1506
  const components = parseComponentInfo(context.sourceCode.text, filename);
1354
1507
  return {
@@ -1383,7 +1536,7 @@ function toKebabCase(value) {
1383
1536
  }
1384
1537
 
1385
1538
  // eslint/rules/documentation/helpers.ts
1386
- import path14 from "path";
1539
+ import path15 from "path";
1387
1540
 
1388
1541
  // constants/rfc2119.ts
1389
1542
  var RFC_2119_KEYWORDS = ["MUST NOT", "MUST", "SHOULD NOT", "SHOULD", "MAY"];
@@ -1398,11 +1551,11 @@ function getFilename(context) {
1398
1551
  return context.filename;
1399
1552
  }
1400
1553
  function isAgentDocument(filename) {
1401
- const base = path14.basename(filename);
1554
+ const base = path15.basename(filename);
1402
1555
  return base === "AGENTS.md" || base === "CLAUDE.md";
1403
1556
  }
1404
1557
  function isDocumentationTemplate(filename) {
1405
- return path14.basename(path14.dirname(filename)) === "_templates";
1558
+ return path15.basename(path15.dirname(filename)) === "_templates";
1406
1559
  }
1407
1560
  function getTextContent(node) {
1408
1561
  if ("value" in node && typeof node.value === "string") return node.value;
@@ -1480,11 +1633,11 @@ var exampleHeadingDescriptionRule = {
1480
1633
 
1481
1634
  // eslint/rules/documentation/glossary-term-linking.ts
1482
1635
  import { readFileSync as readFileSync3 } from "fs";
1483
- import path16 from "path";
1636
+ import path17 from "path";
1484
1637
 
1485
1638
  // eslint/rules/documentation/project-index.ts
1486
1639
  import { readdirSync as readdirSync2, readFileSync as readFileSync2, statSync as statSync2 } from "fs";
1487
- import path15 from "path";
1640
+ import path16 from "path";
1488
1641
  var KIND_BY_SUFFIX = [
1489
1642
  ["-rule.md", "rule"],
1490
1643
  ["-guide.md", "guide"],
@@ -1493,7 +1646,7 @@ var KIND_BY_SUFFIX = [
1493
1646
  ];
1494
1647
  function listMarkdownFiles(dir) {
1495
1648
  return readdirSync2(dir).flatMap((entry) => {
1496
- const entryPath = path15.join(dir, entry);
1649
+ const entryPath = path16.join(dir, entry);
1497
1650
  if (statSync2(entryPath).isDirectory()) {
1498
1651
  return entry.startsWith("_") ? [] : listMarkdownFiles(entryPath);
1499
1652
  }
@@ -1511,11 +1664,11 @@ function getProjectDocs(docsRoot) {
1511
1664
  if (cached) return cached;
1512
1665
  const files = listMarkdownFiles(docsRoot);
1513
1666
  const docs = files.sort((a, b) => a.localeCompare(b)).map((filePath) => {
1514
- const fileName = path15.basename(filePath);
1667
+ const fileName = path16.basename(filePath);
1515
1668
  const kind = KIND_BY_SUFFIX.find(([suffix]) => fileName.endsWith(suffix))?.[1];
1516
1669
  return {
1517
1670
  filePath,
1518
- doc: path15.relative(docsRoot, filePath).split(path15.sep).join("/"),
1671
+ doc: path16.relative(docsRoot, filePath).split(path16.sep).join("/"),
1519
1672
  fileName,
1520
1673
  kind,
1521
1674
  title: extractTitle(filePath)
@@ -1525,12 +1678,12 @@ function getProjectDocs(docsRoot) {
1525
1678
  return docs;
1526
1679
  }
1527
1680
  function findDocsRoot(filePath) {
1528
- let dir = path15.dirname(filePath);
1681
+ let dir = path16.dirname(filePath);
1529
1682
  for (; ; ) {
1530
- if (path15.basename(dir) === "docs" && statSync2(dir).isDirectory()) {
1683
+ if (path16.basename(dir) === "docs" && statSync2(dir).isDirectory()) {
1531
1684
  return dir;
1532
1685
  }
1533
- const parent = path15.dirname(dir);
1686
+ const parent = path16.dirname(dir);
1534
1687
  if (parent === dir) return void 0;
1535
1688
  dir = parent;
1536
1689
  }
@@ -1538,7 +1691,7 @@ function findDocsRoot(filePath) {
1538
1691
 
1539
1692
  // eslint/rules/documentation/glossary-term-linking.ts
1540
1693
  function isGlossary(filePath) {
1541
- return path16.basename(filePath).includes("glossary");
1694
+ return path17.basename(filePath).includes("glossary");
1542
1695
  }
1543
1696
  function termNames(cell) {
1544
1697
  const abbreviation = /\((?<abbreviation>[^()]+)\)/.exec(cell)?.groups?.abbreviation?.trim();
@@ -1631,10 +1784,10 @@ var glossaryTermLinkingRule = {
1631
1784
  const docsRoot = findDocsRoot(filename);
1632
1785
  if (!docsRoot) return;
1633
1786
  const docs = getProjectDocs(docsRoot);
1634
- const guideDir = path16.dirname(filename);
1635
- const referencesDir = path16.join(guideDir, "references");
1787
+ const guideDir = path17.dirname(filename);
1788
+ const referencesDir = path17.join(guideDir, "references");
1636
1789
  const guideReferences = docs.filter(
1637
- (doc) => doc.kind === "reference" && path16.dirname(doc.filePath) === referencesDir
1790
+ (doc) => doc.kind === "reference" && path17.dirname(doc.filePath) === referencesDir
1638
1791
  );
1639
1792
  const glossaryReferences = guideReferences.filter((doc) => isGlossary(doc.filePath));
1640
1793
  if (glossaryReferences.length === 0) return;
@@ -1651,7 +1804,7 @@ var glossaryTermLinkingRule = {
1651
1804
  (section) => section.firstStepLinks.some((link) => {
1652
1805
  const fragment = link.split("#")[1] ?? "";
1653
1806
  if (fragment.toLowerCase() !== anchor) return false;
1654
- return path16.resolve(guideDir, linkTarget(link)) === path16.resolve(ref.filePath);
1807
+ return path17.resolve(guideDir, linkTarget(link)) === path17.resolve(ref.filePath);
1655
1808
  })
1656
1809
  );
1657
1810
  if (!anchored) {
@@ -1687,7 +1840,7 @@ var glossaryTermLinkingRule = {
1687
1840
  };
1688
1841
 
1689
1842
  // eslint/rules/documentation/guide-folder-entry-point.ts
1690
- import path17 from "path";
1843
+ import path18 from "path";
1691
1844
  var guideFolderEntryPointRule = {
1692
1845
  meta: {
1693
1846
  type: "problem",
@@ -1705,13 +1858,13 @@ var guideFolderEntryPointRule = {
1705
1858
  if (!docsRoot) return;
1706
1859
  const docs = getProjectDocs(docsRoot);
1707
1860
  const guideFolders = new Set(
1708
- docs.filter((doc) => ["rules", "references"].includes(path17.basename(path17.dirname(doc.filePath)))).map((doc) => path17.dirname(path17.dirname(doc.filePath))).filter((folder) => path17.resolve(folder) !== path17.resolve(docsRoot))
1861
+ docs.filter((doc) => ["rules", "references"].includes(path18.basename(path18.dirname(doc.filePath)))).map((doc) => path18.dirname(path18.dirname(doc.filePath))).filter((folder) => path18.resolve(folder) !== path18.resolve(docsRoot))
1709
1862
  );
1710
- const currentDir = path17.dirname(filename);
1863
+ const currentDir = path18.dirname(filename);
1711
1864
  if (guideFolders.has(currentDir)) {
1712
- const expectedEntryPoint = `${path17.basename(currentDir)}.md`;
1865
+ const expectedEntryPoint = `${path18.basename(currentDir)}.md`;
1713
1866
  const hasEntryPoint = docs.some(
1714
- (doc) => doc.kind === "guide" && path17.dirname(doc.filePath) === currentDir && doc.fileName === expectedEntryPoint
1867
+ (doc) => doc.kind === "guide" && path18.dirname(doc.filePath) === currentDir && doc.fileName === expectedEntryPoint
1715
1868
  );
1716
1869
  if (!hasEntryPoint) {
1717
1870
  context.report({
@@ -1727,7 +1880,7 @@ var guideFolderEntryPointRule = {
1727
1880
 
1728
1881
  // eslint/rules/documentation/guide-link-anchors.ts
1729
1882
  import { existsSync, readFileSync as readFileSync4 } from "fs";
1730
- import path18 from "path";
1883
+ import path19 from "path";
1731
1884
  function visitSteps(node, check) {
1732
1885
  if (node.type === "list" && node.ordered) {
1733
1886
  for (const child of node.children) check(child);
@@ -1806,7 +1959,7 @@ var guideLinkAnchorsRule = {
1806
1959
  for (const link of links) {
1807
1960
  const [target = "", fragment = ""] = link.url.split("#");
1808
1961
  if (!fragment || !isDocLink(link.url)) continue;
1809
- const targetPath = path18.resolve(path18.dirname(filename), target);
1962
+ const targetPath = path19.resolve(path19.dirname(filename), target);
1810
1963
  if (!existsSync(targetPath)) continue;
1811
1964
  if (documentAnchors(targetPath).has(fragment.toLowerCase())) continue;
1812
1965
  context.report({
@@ -1821,7 +1974,7 @@ var guideLinkAnchorsRule = {
1821
1974
 
1822
1975
  // eslint/rules/documentation/guide-mentions-documents.ts
1823
1976
  import { existsSync as existsSync2 } from "fs";
1824
- import path19 from "path";
1977
+ import path20 from "path";
1825
1978
  function visitSteps2(node, check) {
1826
1979
  if (node.type === "list" && node.ordered) {
1827
1980
  for (const child of node.children) check(child);
@@ -1851,12 +2004,12 @@ var guideMentionsDocumentsRule = {
1851
2004
  if (!filename.endsWith("-guide.md")) return;
1852
2005
  const docsRoot = findDocsRoot(filename);
1853
2006
  if (!docsRoot) return;
1854
- const guideDir = path19.dirname(filename);
1855
- if (path19.basename(filename, ".md") !== path19.basename(guideDir)) return;
2007
+ const guideDir = path20.dirname(filename);
2008
+ if (path20.basename(filename, ".md") !== path20.basename(guideDir)) return;
1856
2009
  const docs = getProjectDocs(docsRoot);
1857
2010
  const owned = docs.filter((doc) => {
1858
- const parent = path19.dirname(doc.filePath);
1859
- return parent === path19.join(guideDir, "rules") || parent === path19.join(guideDir, "references");
2011
+ const parent = path20.dirname(doc.filePath);
2012
+ return parent === path20.join(guideDir, "rules") || parent === path20.join(guideDir, "references");
1860
2013
  });
1861
2014
  const allLinks = [];
1862
2015
  collectMarkdownLinks(node, allLinks);
@@ -1883,7 +2036,7 @@ var guideMentionsDocumentsRule = {
1883
2036
  for (const link of allLinks) {
1884
2037
  const target = linkTarget(link.url);
1885
2038
  if (!target.endsWith(".md")) continue;
1886
- const resolved = path19.normalize(path19.join(guideDir, target));
2039
+ const resolved = path20.normalize(path20.join(guideDir, target));
1887
2040
  if (!existsSync2(resolved)) {
1888
2041
  context.report({
1889
2042
  node: link,
@@ -2562,20 +2715,20 @@ var rulePairedExamplesRule = {
2562
2715
 
2563
2716
  // eslint/rules/documentation/support-document-placement.ts
2564
2717
  import { existsSync as existsSync3 } from "fs";
2565
- import path20 from "path";
2718
+ import path21 from "path";
2566
2719
  function checkPlacement(filename, kind) {
2567
- const parentFolder = path20.basename(path20.dirname(filename));
2720
+ const parentFolder = path21.basename(path21.dirname(filename));
2568
2721
  const expectedParent = `${kind}s`;
2569
2722
  if (parentFolder !== expectedParent) {
2570
2723
  return `${kind} lives in "${parentFolder}/" instead of "${expectedParent}/"`;
2571
2724
  }
2572
- const guideFolderPath = path20.dirname(path20.dirname(filename));
2573
- const guideFolder = path20.basename(guideFolderPath);
2725
+ const guideFolderPath = path21.dirname(path21.dirname(filename));
2726
+ const guideFolder = path21.basename(guideFolderPath);
2574
2727
  if (!guideFolder.endsWith("-guide")) {
2575
2728
  return `${kind} owner folder "${guideFolder}/" does not use the "*-guide/" suffix`;
2576
2729
  }
2577
2730
  const entryPoint = `${guideFolder}.md`;
2578
- if (!existsSync3(path20.join(guideFolderPath, entryPoint))) {
2731
+ if (!existsSync3(path21.join(guideFolderPath, entryPoint))) {
2579
2732
  return `${kind} owner folder "${guideFolder}/" has no "${entryPoint}" entry point`;
2580
2733
  }
2581
2734
  return void 0;
@@ -2610,7 +2763,7 @@ var supportDocumentPlacementRule = {
2610
2763
  };
2611
2764
 
2612
2765
  // eslint/rules/documentation/title-matches-file-name.ts
2613
- import path21 from "path";
2766
+ import path22 from "path";
2614
2767
  function toExpectedFileName(title) {
2615
2768
  return `${title.toLowerCase().replaceAll(/[^a-z0-9]+/g, "-").replace(/^-|-$/g, "")}.md`;
2616
2769
  }
@@ -2630,7 +2783,7 @@ var titleMatchesFileNameRule = {
2630
2783
  if (!filename.endsWith(".md") || isAgentDocument(filename) || isDocumentationTemplate(filename)) return;
2631
2784
  const title = getTextContent(node).trim();
2632
2785
  const expectedFileName = toExpectedFileName(title);
2633
- const actualFileName = path21.basename(filename);
2786
+ const actualFileName = path22.basename(filename);
2634
2787
  if (!title) {
2635
2788
  context.report({
2636
2789
  node,
@@ -2678,7 +2831,7 @@ var documentationRules = {
2678
2831
 
2679
2832
  // eslint/rules/enforce-barrel-exports.ts
2680
2833
  import fs4 from "fs";
2681
- import path22 from "path";
2834
+ import path23 from "path";
2682
2835
  function isPascalCase4(str) {
2683
2836
  return /^[A-Z][A-Za-z0-9]*$/.test(str);
2684
2837
  }
@@ -2687,7 +2840,7 @@ function isKebabCase(str) {
2687
2840
  }
2688
2841
  var SUPPORT_FOLDERS2 = /* @__PURE__ */ new Set(["types", "schemas", "hooks", "constants", "utils", "config", "locales"]);
2689
2842
  function parentComponentName(dirPath, folderName) {
2690
- const componentFile = path22.join(dirPath, `${folderName}.tsx`);
2843
+ const componentFile = path23.join(dirPath, `${folderName}.tsx`);
2691
2844
  if (!fs4.existsSync(componentFile)) return void 0;
2692
2845
  try {
2693
2846
  const exports = parseModule(componentFile).exports;
@@ -2707,12 +2860,12 @@ var enforceBarrelExportsRule = {
2707
2860
  create(context) {
2708
2861
  const filename = context.filename;
2709
2862
  if (!filename) return {};
2710
- const baseName = path22.basename(filename);
2863
+ const baseName = path23.basename(filename);
2711
2864
  const isIndexFile = baseName === "index.ts";
2712
2865
  if (!isIndexFile) return {};
2713
- const dirPath = path22.dirname(filename);
2714
- const folderName = path22.basename(dirPath);
2715
- const parentFolderName = path22.basename(path22.dirname(dirPath));
2866
+ const dirPath = path23.dirname(filename);
2867
+ const folderName = path23.basename(dirPath);
2868
+ const parentFolderName = path23.basename(path23.dirname(dirPath));
2716
2869
  if (SUPPORT_FOLDERS2.has(folderName)) return {};
2717
2870
  if (!isPascalCase4(folderName) && !isKebabCase(folderName)) return {};
2718
2871
  const parentName = parentComponentName(dirPath, folderName);
@@ -2750,7 +2903,7 @@ var enforceBarrelExportsRule = {
2750
2903
  };
2751
2904
 
2752
2905
  // eslint/rules/enforce-cn-merge.ts
2753
- import path23 from "path";
2906
+ import path24 from "path";
2754
2907
  function classCount(str) {
2755
2908
  return str.split(/\s+/).filter(Boolean).length;
2756
2909
  }
@@ -2780,7 +2933,7 @@ var enforceCnMergeRule = {
2780
2933
  create(context) {
2781
2934
  const packageComponents = /* @__PURE__ */ new Set();
2782
2935
  const index = getProjectIndex(sourceRootOf(context));
2783
- const module = index?.modules.get(path23.resolve(context.filename));
2936
+ const module = index?.modules.get(path24.resolve(context.filename));
2784
2937
  for (const moduleImport of module?.imports ?? []) {
2785
2938
  if (moduleImport.specifier.startsWith(".") || moduleImport.specifier.startsWith("@/")) continue;
2786
2939
  for (const name of moduleImport.names) {
@@ -2934,7 +3087,7 @@ var enforceCvaVariantPropsRule = {
2934
3087
  };
2935
3088
 
2936
3089
  // eslint/rules/enum-placement.ts
2937
- import path24 from "path";
3090
+ import path25 from "path";
2938
3091
  var enumPlacementRule = {
2939
3092
  meta: {
2940
3093
  schema: [],
@@ -2944,10 +3097,10 @@ var enumPlacementRule = {
2944
3097
  }
2945
3098
  },
2946
3099
  create(context) {
2947
- const filename = path24.resolve(context.filename);
3100
+ const filename = path25.resolve(context.filename);
2948
3101
  const sourceRoot = sourceRootOf(context);
2949
- if (!filename.startsWith(sourceRoot + path24.sep)) return {};
2950
- if (path24.basename(path24.dirname(filename)) === "constants") return {};
3102
+ if (!filename.startsWith(sourceRoot + path25.sep)) return {};
3103
+ if (path25.basename(path25.dirname(filename)) === "constants") return {};
2951
3104
  return {
2952
3105
  TSEnumDeclaration(node) {
2953
3106
  context.report({
@@ -2985,7 +3138,7 @@ var fileLengthRule = {
2985
3138
  };
2986
3139
 
2987
3140
  // eslint/rules/filename-case.ts
2988
- import path25 from "path";
3141
+ import path26 from "path";
2989
3142
  var NEXT_ROUTING_FILES2 = /* @__PURE__ */ new Set([
2990
3143
  "page",
2991
3144
  "layout",
@@ -3031,11 +3184,11 @@ var filenameCaseRule = {
3031
3184
  if (!normalized.includes("/src/")) {
3032
3185
  return {};
3033
3186
  }
3034
- const ext = path25.extname(filename);
3035
- let base = path25.basename(filename, ext);
3036
- const baseExt = path25.extname(base);
3187
+ const ext = path26.extname(filename);
3188
+ let base = path26.basename(filename, ext);
3189
+ const baseExt = path26.extname(base);
3037
3190
  if (baseExt && COMPOUND_SUFFIXES.has(baseExt.slice(1))) {
3038
- base = path25.basename(base, baseExt);
3191
+ base = path26.basename(base, baseExt);
3039
3192
  }
3040
3193
  if (NEXT_ROUTING_FILES2.has(base)) {
3041
3194
  return {};
@@ -3048,21 +3201,21 @@ var filenameCaseRule = {
3048
3201
  if (component?.smart && !isPascalCase5(base)) {
3049
3202
  context.report({
3050
3203
  node,
3051
- message: `Smart component files must use PascalCase.tsx. Filename "${path25.basename(filename)}" is not PascalCase.`
3204
+ message: `Smart component files must use PascalCase.tsx. Filename "${path26.basename(filename)}" is not PascalCase.`
3052
3205
  });
3053
3206
  return;
3054
3207
  }
3055
3208
  if (component && !component.smart && !isKebabCase2(base)) {
3056
3209
  context.report({
3057
3210
  node,
3058
- message: `Dumb component files must use kebab-case.tsx. Filename "${path25.basename(filename)}" is not kebab-case.`
3211
+ message: `Dumb component files must use kebab-case.tsx. Filename "${path26.basename(filename)}" is not kebab-case.`
3059
3212
  });
3060
3213
  return;
3061
3214
  }
3062
3215
  if (!component && !(isPascalCase5(base) || isKebabCase2(base))) {
3063
3216
  context.report({
3064
3217
  node,
3065
- message: `Filename "${path25.basename(filename)}" does not match pasika conventions. Component files must be PascalCase.tsx (smart) or kebab-case.tsx (dumb).`
3218
+ message: `Filename "${path26.basename(filename)}" does not match pasika conventions. Component files must be PascalCase.tsx (smart) or kebab-case.tsx (dumb).`
3066
3219
  });
3067
3220
  }
3068
3221
  }
@@ -3081,14 +3234,14 @@ function report2(context, filename, ext) {
3081
3234
  context.report({
3082
3235
  node,
3083
3236
  loc: { line: 1, column: 0 },
3084
- message: `Filename "${path25.basename(filename)}" does not match pasika conventions. ${convention}`
3237
+ message: `Filename "${path26.basename(filename)}" does not match pasika conventions. ${convention}`
3085
3238
  });
3086
3239
  }
3087
3240
  };
3088
3241
  }
3089
3242
 
3090
3243
  // eslint/rules/hook-complexity.ts
3091
- import path26 from "path";
3244
+ import path27 from "path";
3092
3245
  import ts3 from "typescript";
3093
3246
  var REACT_HOOKS = /* @__PURE__ */ new Set([
3094
3247
  "useState",
@@ -3213,9 +3366,9 @@ var hookComplexityRule = {
3213
3366
  create(context) {
3214
3367
  const filename = context.filename;
3215
3368
  const sourceRoot = sourceRootOf(context);
3216
- const relative = path26.relative(sourceRoot, filename);
3369
+ const relative = path27.relative(sourceRoot, filename);
3217
3370
  if (relative.startsWith("..")) return {};
3218
- const segments = relative.split(path26.sep);
3371
+ const segments = relative.split(path27.sep);
3219
3372
  const sourceText = context.sourceCode.text;
3220
3373
  const index = getProjectIndex(sourceRoot);
3221
3374
  const localHookCalls = /* @__PURE__ */ new Set();
@@ -3302,7 +3455,7 @@ var hookComplexityRule = {
3302
3455
  };
3303
3456
 
3304
3457
  // eslint/rules/hook-extraction.ts
3305
- import path27 from "path";
3458
+ import path28 from "path";
3306
3459
  var hookExtractionRule = {
3307
3460
  meta: {
3308
3461
  schema: [],
@@ -3313,7 +3466,7 @@ var hookExtractionRule = {
3313
3466
  },
3314
3467
  create(context) {
3315
3468
  const sourceRoot = sourceRootOf(context);
3316
- const file = path27.resolve(context.filename);
3469
+ const file = path28.resolve(context.filename);
3317
3470
  const segments = segmentsOf(file, sourceRoot);
3318
3471
  if (segments.length === 0) return {};
3319
3472
  const index = getProjectIndex(sourceRoot);
@@ -3340,14 +3493,14 @@ var hookExtractionRule = {
3340
3493
 
3341
3494
  // eslint/rules/http-error-usage.ts
3342
3495
  import { readFileSync as readFileSync5 } from "fs";
3343
- import path28 from "path";
3496
+ import path29 from "path";
3344
3497
  import ts4 from "typescript";
3345
3498
  var HTTP_ERROR = "HttpError";
3346
3499
  var ROUTE_FILE = "route.ts";
3347
- var DOC2 = "docs/next-codebase-guide/rules/route-handler-rule.md";
3500
+ var DOC3 = "docs/next-codebase-guide/rules/route-handler-rule.md";
3348
3501
  var HERITAGE_DEPTH = 5;
3349
- var HANDS_ERROR_BACK = `A delegated module must throw the HttpError it reports a failure with, not return it. See ${DOC2}`;
3350
- var delegatedModuleMessage = (name) => `A delegated module must report a failure by throwing an HttpError, not "${name}". See ${DOC2}`;
3502
+ var HANDS_ERROR_BACK = `A delegated module must throw the HttpError it reports a failure with, not return it. See ${DOC3}`;
3503
+ var delegatedModuleMessage = (name) => `A delegated module must report a failure by throwing an HttpError, not "${name}". See ${DOC3}`;
3351
3504
  function constructedErrorName(node) {
3352
3505
  if (node === void 0) return void 0;
3353
3506
  if (node.type === "NewExpression") {
@@ -3384,13 +3537,13 @@ function parentClassOf(file, name) {
3384
3537
  return void 0;
3385
3538
  }
3386
3539
  function importedFrom(file, name, sourceRoot, index) {
3387
- const module = index.modules.get(path28.resolve(file));
3540
+ const module = index.modules.get(path29.resolve(file));
3388
3541
  const moduleImport = module?.imports.find((entry) => entry.names.includes(name));
3389
3542
  if (!moduleImport) return void 0;
3390
3543
  return resolveSpecifier(file, moduleImport.specifier, sourceRoot);
3391
3544
  }
3392
3545
  function isHttpErrorClass(file, name, sourceRoot, index) {
3393
- let currentFile = path28.resolve(file);
3546
+ let currentFile = path29.resolve(file);
3394
3547
  let currentName = name;
3395
3548
  for (let depth = 0; depth <= HERITAGE_DEPTH; depth += 1) {
3396
3549
  if (currentName === HTTP_ERROR) return true;
@@ -3411,7 +3564,7 @@ function pipelineFiles(sourceRoot) {
3411
3564
  if (!index) return void 0;
3412
3565
  if (pipelineCache?.index === index) return pipelineCache.files;
3413
3566
  const files = /* @__PURE__ */ new Set();
3414
- const queue = [...index.modules.keys()].filter((file) => path28.basename(file) === ROUTE_FILE);
3567
+ const queue = [...index.modules.keys()].filter((file) => path29.basename(file) === ROUTE_FILE);
3415
3568
  while (queue.length > 0) {
3416
3569
  const file = queue.pop();
3417
3570
  if (file === void 0 || files.has(file)) continue;
@@ -3434,7 +3587,7 @@ var httpErrorUsageRule = {
3434
3587
  },
3435
3588
  create(context) {
3436
3589
  const sourceRoot = sourceRootOf(context);
3437
- const file = path28.resolve(context.filename);
3590
+ const file = path29.resolve(context.filename);
3438
3591
  let delegated;
3439
3592
  function inPipeline() {
3440
3593
  delegated ??= pipelineFiles(sourceRoot)?.has(file) ?? false;
@@ -3469,7 +3622,7 @@ var httpErrorUsageRule = {
3469
3622
 
3470
3623
  // eslint/rules/husky/husky-hook.ts
3471
3624
  import { existsSync as existsSync4, readFileSync as readFileSync6 } from "fs";
3472
- import path29 from "path";
3625
+ import path30 from "path";
3473
3626
  function memberName(member) {
3474
3627
  return member.name.type === "String" ? member.name.value : member.name.name;
3475
3628
  }
@@ -3487,7 +3640,7 @@ var huskyHookRule = {
3487
3640
  const root = node.body;
3488
3641
  if (root.type !== "Object") return;
3489
3642
  if (!context.filename.endsWith("package.json")) return;
3490
- const hookPath = path29.join(context.cwd, ".husky", "pre-commit");
3643
+ const hookPath = path30.join(context.cwd, ".husky", "pre-commit");
3491
3644
  if (!existsSync4(hookPath)) {
3492
3645
  context.report({
3493
3646
  node,
@@ -3514,7 +3667,7 @@ var huskyHookRule = {
3514
3667
  if (!content.includes("libyear --limit-major-individual=1")) {
3515
3668
  context.report({ node, message: ".husky/pre-commit must run npx libyear --limit-major-individual=1." });
3516
3669
  }
3517
- const suppressionsPath = path29.join(context.cwd, "eslint-suppressions.json");
3670
+ const suppressionsPath = path30.join(context.cwd, "eslint-suppressions.json");
3518
3671
  if (existsSync4(suppressionsPath)) {
3519
3672
  requireNamedScript("lint:prune");
3520
3673
  const pruneIndex = content.indexOf("npm run lint:prune");
@@ -3546,28 +3699,28 @@ var huskyRules = {
3546
3699
  };
3547
3700
 
3548
3701
  // eslint/rules/import-boundaries.ts
3549
- import path30 from "path";
3702
+ import path31 from "path";
3550
3703
  var rootSupportFolders = /* @__PURE__ */ new Set(["config", "constants", "hooks", "locales", "schemas", "types", "utils"]);
3551
3704
  var moduleExtensions = /* @__PURE__ */ new Set([".cjs", ".cts", ".js", ".jsx", ".mjs", ".mts", ".ts", ".tsx"]);
3552
3705
  var styleExtensions = /* @__PURE__ */ new Set([".css", ".less", ".sass", ".scss"]);
3553
3706
  function resolveSourceImport(sourceRoot, filename, importPath) {
3554
3707
  if (importPath.startsWith("@/")) {
3555
- return path30.resolve(sourceRoot, importPath.slice(2));
3708
+ return path31.resolve(sourceRoot, importPath.slice(2));
3556
3709
  }
3557
3710
  if (importPath.startsWith(".")) {
3558
- return path30.resolve(path30.dirname(filename), importPath);
3711
+ return path31.resolve(path31.dirname(filename), importPath);
3559
3712
  }
3560
3713
  return void 0;
3561
3714
  }
3562
3715
  function sourceSegments(sourceRoot, absolutePath) {
3563
- const relativePath = path30.relative(sourceRoot, absolutePath);
3564
- if (relativePath.startsWith("..") || path30.isAbsolute(relativePath)) {
3716
+ const relativePath = path31.relative(sourceRoot, absolutePath);
3717
+ if (relativePath.startsWith("..") || path31.isAbsolute(relativePath)) {
3565
3718
  return void 0;
3566
3719
  }
3567
- return relativePath.split(path30.sep);
3720
+ return relativePath.split(path31.sep);
3568
3721
  }
3569
3722
  function relativeSpecifier(filename, resolvedPath) {
3570
- const relativePath = path30.relative(path30.dirname(filename), resolvedPath).split(path30.sep).join("/");
3723
+ const relativePath = path31.relative(path31.dirname(filename), resolvedPath).split(path31.sep).join("/");
3571
3724
  return relativePath.startsWith(".") ? relativePath : `./${relativePath}`;
3572
3725
  }
3573
3726
  function aliasSpecifier(sourceRoot, resolvedPath) {
@@ -3606,7 +3759,7 @@ var importBoundariesRule = {
3606
3759
  }
3607
3760
  const [importerLayer = "", importerFeature] = importer;
3608
3761
  const [importedLayer = "", importedFeature] = imported;
3609
- const extension = path30.extname(importPath);
3762
+ const extension = path31.extname(importPath);
3610
3763
  const isCodeModule = !extension || moduleExtensions.has(extension);
3611
3764
  const isAppLocalStyleImport = importerLayer === "app" && importedLayer === "app" && styleExtensions.has(extension);
3612
3765
  const importedIsRootSupport = rootSupportFolders.has(importedLayer);
@@ -3704,7 +3857,7 @@ var importSpacingRule = {
3704
3857
  };
3705
3858
 
3706
3859
  // eslint/rules/import-through-index.ts
3707
- import path31 from "path";
3860
+ import path32 from "path";
3708
3861
  var importThroughIndexRule = {
3709
3862
  meta: {
3710
3863
  schema: [],
@@ -3714,7 +3867,7 @@ var importThroughIndexRule = {
3714
3867
  }
3715
3868
  },
3716
3869
  create(context) {
3717
- const filename = path31.resolve(context.filename);
3870
+ const filename = path32.resolve(context.filename);
3718
3871
  const sourceRoot = sourceRootOf2(context, filename);
3719
3872
  return {
3720
3873
  Program(node) {
@@ -3726,7 +3879,7 @@ var importThroughIndexRule = {
3726
3879
  (segment) => ["constants", "types", "schemas"].includes(segment)
3727
3880
  );
3728
3881
  const supportFolder = supportFolderIndex >= 0 ? targetSegments[supportFolderIndex] : void 0;
3729
- if (!supportFolder || path31.basename(target).startsWith("index.")) continue;
3882
+ if (!supportFolder || path32.basename(target).startsWith("index.")) continue;
3730
3883
  const folderIndex = targetSegments.slice(0, supportFolderIndex + 1);
3731
3884
  const expected = `@/${folderIndex.join("/")}`;
3732
3885
  context.report({
@@ -3748,14 +3901,14 @@ function importSpecifiers(source) {
3748
3901
  return specifiers;
3749
3902
  }
3750
3903
  function sourceRootOf2(context, filename) {
3751
- const marker = `${path31.sep}src${path31.sep}`;
3904
+ const marker = `${path32.sep}src${path32.sep}`;
3752
3905
  const srcIndex = filename.lastIndexOf(marker);
3753
3906
  if (srcIndex >= 0) return filename.slice(0, srcIndex + marker.length - 1);
3754
- return path31.resolve(context.cwd ?? process.cwd(), "src");
3907
+ return path32.resolve(context.cwd ?? process.cwd(), "src");
3755
3908
  }
3756
3909
 
3757
3910
  // eslint/rules/interactive-component.ts
3758
- import path32 from "path";
3911
+ import path33 from "path";
3759
3912
  var INTERACTIVE_TAGS = /* @__PURE__ */ new Set([
3760
3913
  "a",
3761
3914
  "button",
@@ -3911,8 +4064,8 @@ var interactiveComponentRule = {
3911
4064
  },
3912
4065
  create(context) {
3913
4066
  if (!context.filename.endsWith(".tsx") && !context.filename.endsWith(".jsx")) return {};
3914
- const filename = path32.resolve(context.filename);
3915
- const base = path32.basename(filename, path32.extname(filename));
4067
+ const filename = path33.resolve(context.filename);
4068
+ const base = path33.basename(filename, path33.extname(filename));
3916
4069
  if (NEXT_ROUTING_FILES3.has(base)) return {};
3917
4070
  return {
3918
4071
  JSXElement(node) {
@@ -4036,9 +4189,9 @@ var jsxHygieneRule = {
4036
4189
  };
4037
4190
 
4038
4191
  // eslint/rules/locale-dotted-path.ts
4039
- import path33 from "path";
4192
+ import path34 from "path";
4040
4193
  function isInLocalesDir(filename) {
4041
- const segments = path33.resolve(filename).split(path33.sep);
4194
+ const segments = path34.resolve(filename).split(path34.sep);
4042
4195
  const srcIdx = segments.lastIndexOf("src");
4043
4196
  return srcIdx !== -1 && segments[srcIdx + 1] === "locales";
4044
4197
  }
@@ -4087,7 +4240,7 @@ var localeDottedPathRule = {
4087
4240
  };
4088
4241
 
4089
4242
  // eslint/rules/locale-key-shape.ts
4090
- import path34 from "path";
4243
+ import path35 from "path";
4091
4244
  var MAX_KEY_LENGTH = 30;
4092
4245
  var ROLE_POSTFIXES = /* @__PURE__ */ new Set([
4093
4246
  "Button",
@@ -4137,7 +4290,7 @@ var ROLE_POSTFIXES = /* @__PURE__ */ new Set([
4137
4290
  var CAMEL_CASE = /^[a-z][a-zA-Z0-9]*$/;
4138
4291
  var ENGLISH = /^[A-Za-z0-9_]*$/;
4139
4292
  function isLocalesFile(filename) {
4140
- const segments = path34.resolve(filename).split(path34.sep);
4293
+ const segments = path35.resolve(filename).split(path35.sep);
4141
4294
  const srcIdx = segments.lastIndexOf("src");
4142
4295
  return srcIdx !== -1 && segments[srcIdx + 1] === "locales";
4143
4296
  }
@@ -4209,7 +4362,7 @@ var localeKeyShapeRule = {
4209
4362
 
4210
4363
  // eslint/rules/locale-placement.ts
4211
4364
  import { readFileSync as readFileSync7 } from "fs";
4212
- import path35 from "path";
4365
+ import path36 from "path";
4213
4366
  import ts6 from "typescript";
4214
4367
  var LOCALE_ACCESS = /\blocales\.(?<key>[A-Za-z_$][\w$]*)/g;
4215
4368
  var camelCase = (name) => name.replace(/-[a-z]/g, (match) => match.slice(1).toUpperCase());
@@ -4256,7 +4409,7 @@ var localePlacementRule = {
4256
4409
  },
4257
4410
  create(context) {
4258
4411
  const sourceRoot = sourceRootOf(context);
4259
- const file = path35.resolve(context.filename);
4412
+ const file = path36.resolve(context.filename);
4260
4413
  const segments = segmentsOf(file, sourceRoot);
4261
4414
  if (segments.length === 0) return {};
4262
4415
  const index = getProjectIndex(sourceRoot);
@@ -4334,9 +4487,9 @@ var localePlacementRule = {
4334
4487
  };
4335
4488
 
4336
4489
  // eslint/rules/locales-location.ts
4337
- import path36 from "path";
4490
+ import path37 from "path";
4338
4491
  function isLocalesFile2(filename) {
4339
- const segments = path36.resolve(filename).split(path36.sep);
4492
+ const segments = path37.resolve(filename).split(path37.sep);
4340
4493
  const srcIdx = segments.lastIndexOf("src");
4341
4494
  return srcIdx !== -1 && segments[srcIdx + 1] === "locales";
4342
4495
  }
@@ -4416,7 +4569,7 @@ var localesLocationRule = {
4416
4569
  create(context) {
4417
4570
  if (isLocalesFile2(context.filename) || isTestFile(context.filename)) return {};
4418
4571
  const filename = context.filename;
4419
- const segments = path36.resolve(filename).split(path36.sep);
4572
+ const segments = path37.resolve(filename).split(path37.sep);
4420
4573
  const srcIdx = segments.lastIndexOf("src");
4421
4574
  if (srcIdx === -1) return {};
4422
4575
  const folder = segments[srcIdx + 1];
@@ -4501,7 +4654,7 @@ var localesLocationRule = {
4501
4654
  };
4502
4655
 
4503
4656
  // eslint/rules/named-exports.ts
4504
- import path37 from "path";
4657
+ import path38 from "path";
4505
4658
  var FRAMEWORK_DEFAULT_EXPORT_FILES = /* @__PURE__ */ new Set([
4506
4659
  // App Router routing files
4507
4660
  "default",
@@ -4523,9 +4676,9 @@ var FRAMEWORK_DEFAULT_EXPORT_FILES = /* @__PURE__ */ new Set([
4523
4676
  "twitter-image"
4524
4677
  ]);
4525
4678
  function isFrameworkDefaultExportFile(filename) {
4526
- const normalized = filename.replaceAll(path37.sep, "/");
4679
+ const normalized = filename.replaceAll(path38.sep, "/");
4527
4680
  if (!normalized.includes("/src/app/")) return false;
4528
- const basename = path37.basename(filename, path37.extname(filename));
4681
+ const basename = path38.basename(filename, path38.extname(filename));
4529
4682
  return FRAMEWORK_DEFAULT_EXPORT_FILES.has(basename);
4530
4683
  }
4531
4684
  var namedExportsRule = {
@@ -4788,8 +4941,8 @@ var noMixedConcernsRule = {
4788
4941
  };
4789
4942
 
4790
4943
  // eslint/rules/no-redundant-alias.ts
4791
- import path38 from "path";
4792
- var DOC3 = "See docs/next-codebase-guide/rules/redundant-aliases-rule.md";
4944
+ import path39 from "path";
4945
+ var DOC4 = "See docs/next-codebase-guide/rules/redundant-aliases-rule.md";
4793
4946
  var VALUE_SENTINELS = /* @__PURE__ */ new Set(["undefined", "NaN", "Infinity"]);
4794
4947
  var HTTP_METHODS = /* @__PURE__ */ new Set(["GET", "POST", "PUT", "PATCH", "DELETE", "HEAD", "OPTIONS"]);
4795
4948
  var PRIMITIVE_TYPE_NAMES = {
@@ -4821,7 +4974,7 @@ function aliasedTypeName(annotation) {
4821
4974
  function aliasMessage(alias, source) {
4822
4975
  const aliasName = alias ?? "This declaration";
4823
4976
  const sourceName = source ?? "the original symbol";
4824
- return `"${aliasName}" only renames "${sourceName}". Use "${sourceName}" directly or rename the original symbol and its consumers. ${DOC3}`;
4977
+ return `"${aliasName}" only renames "${sourceName}". Use "${sourceName}" directly or rename the original symbol and its consumers. ${DOC4}`;
4825
4978
  }
4826
4979
  var noRedundantAliasRule = {
4827
4980
  meta: {
@@ -4838,7 +4991,7 @@ var noRedundantAliasRule = {
4838
4991
  const declaration = node.parent;
4839
4992
  if (declaration.type !== "VariableDeclaration" || declaration.kind !== "const") return;
4840
4993
  const exported = declaration.parent.type === "ExportNamedDeclaration";
4841
- const frameworkRouteAlias = path38.basename(context.filename) === "route.ts" && exported && HTTP_METHODS.has(node.id.name);
4994
+ const frameworkRouteAlias = path39.basename(context.filename) === "route.ts" && exported && HTTP_METHODS.has(node.id.name);
4842
4995
  if (frameworkRouteAlias || VALUE_SENTINELS.has(node.init.name)) return;
4843
4996
  context.report({
4844
4997
  node,
@@ -4862,7 +5015,7 @@ var noRedundantAliasRule = {
4862
5015
  const source = specifier.local.name;
4863
5016
  const alias = specifier.exported.name;
4864
5017
  if (source === alias) continue;
4865
- const frameworkRouteAlias = path38.basename(context.filename) === "route.ts" && HTTP_METHODS.has(alias);
5018
+ const frameworkRouteAlias = path39.basename(context.filename) === "route.ts" && HTTP_METHODS.has(alias);
4866
5019
  if (frameworkRouteAlias) continue;
4867
5020
  context.report({
4868
5021
  node: specifier,
@@ -4887,7 +5040,7 @@ var noRedundantAliasRule = {
4887
5040
  };
4888
5041
 
4889
5042
  // eslint/rules/no-util-barrel.ts
4890
- import path39 from "path";
5043
+ import path40 from "path";
4891
5044
  var noUtilBarrelRule = {
4892
5045
  meta: {
4893
5046
  schema: [],
@@ -4897,7 +5050,7 @@ var noUtilBarrelRule = {
4897
5050
  }
4898
5051
  },
4899
5052
  create(context) {
4900
- const filename = path39.resolve(context.filename);
5053
+ const filename = path40.resolve(context.filename);
4901
5054
  const sourceRoot = sourceRootOf3(context, filename);
4902
5055
  return {
4903
5056
  Program(node) {
@@ -4906,7 +5059,7 @@ var noUtilBarrelRule = {
4906
5059
  if (!target) continue;
4907
5060
  const segments = target.replace(/\\/g, "/").split("/");
4908
5061
  const utilsIndex = segments.lastIndexOf("utils");
4909
- if (utilsIndex < 0 || !path39.basename(target).startsWith("index.")) continue;
5062
+ if (utilsIndex < 0 || !path40.basename(target).startsWith("index.")) continue;
4910
5063
  context.report({
4911
5064
  node,
4912
5065
  message: `Import utilities directly instead of through "${specifier}". See docs/next-codebase-guide/rules/utilities-rule.md`
@@ -4926,10 +5079,10 @@ function importSpecifiers2(source) {
4926
5079
  return specifiers;
4927
5080
  }
4928
5081
  function sourceRootOf3(context, filename) {
4929
- const marker = `${path39.sep}src${path39.sep}`;
5082
+ const marker = `${path40.sep}src${path40.sep}`;
4930
5083
  const srcIndex = filename.lastIndexOf(marker);
4931
5084
  if (srcIndex >= 0) return filename.slice(0, srcIndex + marker.length - 1);
4932
- return path39.resolve(context.cwd ?? process.cwd(), "src");
5085
+ return path40.resolve(context.cwd ?? process.cwd(), "src");
4933
5086
  }
4934
5087
 
4935
5088
  // eslint/rules/package-json/exact-version.ts
@@ -5148,7 +5301,7 @@ var nextjsStackRule = {
5148
5301
 
5149
5302
  // eslint/rules/package-json/vitest-coverage.ts
5150
5303
  import { existsSync as existsSync5, readFileSync as readFileSync8 } from "fs";
5151
- import path40 from "path";
5304
+ import path41 from "path";
5152
5305
  function memberName5(member) {
5153
5306
  return member.name.type === "String" ? member.name.value : member.name.name;
5154
5307
  }
@@ -5172,7 +5325,8 @@ var THRESHOLD_METRICS = ["lines", "functions", "branches", "statements"];
5172
5325
  var SOURCE_GLOB_PATTERN2 = /(?:^|[^a-z])(?:[cm]?[jt]sx?)(?:[^a-z]|$)/i;
5173
5326
  var COVERAGE_FLAG_PATTERN = /(?:^|\s)--coverage(?:[=\s]|$)/;
5174
5327
  var RELATED_PATTERN = /\brelated\b/;
5175
- var AUTO_UPDATE_PATTERN = /autoUpdate\s*:\s*\(\s*newThreshold\s*,\s*previousThreshold\s*\)\s*=>\s*Math\.max\(\s*Number\(\s*String\(\s*previousThreshold\s*\)\s*\)\s*,\s*Math\.floor\(\s*\(\s*newThreshold\s*-\s*0\.1\s*\)\s*\*\s*10\s*\)\s*\/\s*10\s*\)/;
5328
+ var AUTO_UPDATE_TRUE_PATTERN = /autoUpdate\s*:\s*true\b/;
5329
+ var BUFFERED_AUTO_UPDATE_PATTERN = /autoUpdate\s*:\s*\(\s*newThreshold\s*,\s*previousThreshold\s*\)\s*=>\s*Math\.max\(\s*Number\(\s*String\(\s*previousThreshold\s*\)\s*\)\s*,\s*Math\.floor\(\s*\(\s*newThreshold\s*-\s*0\.1\s*\)\s*\*\s*10\s*\)\s*\/\s*10\s*\)/;
5176
5330
  var vitestCoverageRule = {
5177
5331
  meta: {
5178
5332
  schema: [],
@@ -5217,7 +5371,7 @@ var vitestCoverageRule = {
5217
5371
  message: 'package.json must declare a "test:unit:coverage" script that runs Vitest with coverage.'
5218
5372
  });
5219
5373
  }
5220
- const configName = VITEST_CONFIG_NAMES.find((name) => existsSync5(path40.join(context.cwd, name)));
5374
+ const configName = VITEST_CONFIG_NAMES.find((name) => existsSync5(path41.join(context.cwd, name)));
5221
5375
  if (!configName) {
5222
5376
  context.report({
5223
5377
  node,
@@ -5225,16 +5379,16 @@ var vitestCoverageRule = {
5225
5379
  });
5226
5380
  return;
5227
5381
  }
5228
- const content = readFileSync8(path40.join(context.cwd, configName), "utf8");
5382
+ const content = readFileSync8(path41.join(context.cwd, configName), "utf8");
5229
5383
  for (const metric of THRESHOLD_METRICS) {
5230
5384
  if (!new RegExp(`\\b${metric}\\s*:\\s*[1-9]\\d*`).test(content)) {
5231
5385
  context.report({ node, message: `${configName} must set a coverage threshold above zero for ${metric}.` });
5232
5386
  }
5233
5387
  }
5234
- if (!AUTO_UPDATE_PATTERN.test(content)) {
5388
+ if (!AUTO_UPDATE_TRUE_PATTERN.test(content) && !BUFFERED_AUTO_UPDATE_PATTERN.test(content)) {
5235
5389
  context.report({
5236
5390
  node,
5237
- message: `${configName} must set coverage.thresholds.autoUpdate to the monotonic 0.1-point buffered formatter.`
5391
+ message: `${configName} must enable coverage.thresholds.autoUpdate with true or the monotonic 0.1-point buffered formatter.`
5238
5392
  });
5239
5393
  }
5240
5394
  const stagedTests = scriptMembers.find((member) => memberName5(member) === "test:unit:staged");
@@ -5271,7 +5425,7 @@ var nextjsPackageJsonRules = {
5271
5425
  };
5272
5426
 
5273
5427
  // eslint/rules/prefer-enum.ts
5274
- import path41 from "path";
5428
+ import path42 from "path";
5275
5429
  function isConstAssertion(node) {
5276
5430
  const typeAnnotation = node.typeAnnotation;
5277
5431
  return typeAnnotation?.type === "TSTypeReference" && typeAnnotation.typeName?.type === "Identifier" && typeAnnotation.typeName.name === "const";
@@ -5323,9 +5477,9 @@ var preferEnumRule = {
5323
5477
  }
5324
5478
  },
5325
5479
  create(context) {
5326
- const filename = path41.resolve(context.filename);
5480
+ const filename = path42.resolve(context.filename);
5327
5481
  const sourceRoot = sourceRootOf(context);
5328
- if (!filename.startsWith(sourceRoot + path41.sep)) return {};
5482
+ if (!filename.startsWith(sourceRoot + path42.sep)) return {};
5329
5483
  const objectSchemas = /* @__PURE__ */ new Map();
5330
5484
  const discriminatedUnions = [];
5331
5485
  const reportedDiscriminants = /* @__PURE__ */ new Set();
@@ -5396,7 +5550,7 @@ var preferEnumRule = {
5396
5550
  };
5397
5551
 
5398
5552
  // eslint/rules/pure-function-extract.ts
5399
- import path42 from "path";
5553
+ import path43 from "path";
5400
5554
  var ROUTE_HANDLER_EXPORT_NAMES = /* @__PURE__ */ new Set([
5401
5555
  "GET",
5402
5556
  "POST",
@@ -5461,12 +5615,12 @@ var pureFunctionExtractRule = {
5461
5615
  },
5462
5616
  create(context) {
5463
5617
  const filename = context.filename;
5464
- const isRouteFile = path42.basename(filename) === "route.ts";
5618
+ const isRouteFile = path43.basename(filename) === "route.ts";
5465
5619
  const isComponentFile = filename.endsWith(".tsx") || filename.endsWith(".jsx");
5466
5620
  const sourceRoot = sourceRootOf(context);
5467
- const relative = path42.relative(sourceRoot, filename);
5621
+ const relative = path43.relative(sourceRoot, filename);
5468
5622
  if (relative.startsWith("..")) return {};
5469
- const segments = relative.split(path42.sep);
5623
+ const segments = relative.split(path43.sep);
5470
5624
  const folders = segments.slice(0, -1);
5471
5625
  const isHookSupportFile = folders.includes("hooks") && /\.(?:[cm]?[jt]s)$/.test(filename);
5472
5626
  if (!isComponentFile && !isRouteFile && !isHookSupportFile) return {};
@@ -5707,7 +5861,7 @@ var repeatedStructureRule = {
5707
5861
 
5708
5862
  // eslint/rules/require-barrel-star-exports.ts
5709
5863
  import fs5 from "fs";
5710
- import path43 from "path";
5864
+ import path44 from "path";
5711
5865
  var SUPPORT_FOLDERS3 = /* @__PURE__ */ new Set(["constants", "types", "schemas"]);
5712
5866
  var INDEX_NAMES = /* @__PURE__ */ new Set(["index.ts", "index.tsx", "index.mts", "index.cts"]);
5713
5867
  var MODULE_EXTENSIONS3 = [".ts", ".tsx", ".mts", ".cts", ".js", ".jsx", ".mjs", ".cjs"];
@@ -5715,9 +5869,9 @@ function resolveSiblingModule(indexFile, specifier) {
5715
5869
  if (!specifier.startsWith("./")) return void 0;
5716
5870
  const relative = specifier.slice(2);
5717
5871
  if (!relative || relative.includes("/")) return void 0;
5718
- const directory = path43.dirname(indexFile);
5719
- const direct = path43.resolve(directory, relative);
5720
- const candidates = path43.extname(direct) ? [direct] : MODULE_EXTENSIONS3.map((extension) => `${direct}${extension}`);
5872
+ const directory = path44.dirname(indexFile);
5873
+ const direct = path44.resolve(directory, relative);
5874
+ const candidates = path44.extname(direct) ? [direct] : MODULE_EXTENSIONS3.map((extension) => `${direct}${extension}`);
5721
5875
  return candidates.find((candidate) => fs5.existsSync(candidate) && fs5.statSync(candidate).isFile());
5722
5876
  }
5723
5877
  var requireBarrelStarExportsRule = {
@@ -5730,9 +5884,9 @@ var requireBarrelStarExportsRule = {
5730
5884
  fixable: "code"
5731
5885
  },
5732
5886
  create(context) {
5733
- const filename = path43.resolve(context.filename);
5734
- if (!INDEX_NAMES.has(path43.basename(filename))) return {};
5735
- if (!SUPPORT_FOLDERS3.has(path43.basename(path43.dirname(filename)))) return {};
5887
+ const filename = path44.resolve(context.filename);
5888
+ if (!INDEX_NAMES.has(path44.basename(filename))) return {};
5889
+ if (!SUPPORT_FOLDERS3.has(path44.basename(path44.dirname(filename)))) return {};
5736
5890
  return {
5737
5891
  ExportNamedDeclaration(node) {
5738
5892
  const sourceNode = node.source;
@@ -5785,7 +5939,7 @@ var requireBarrelStarExportsRule = {
5785
5939
  };
5786
5940
 
5787
5941
  // eslint/rules/root-support-placement.ts
5788
- import path44 from "path";
5942
+ import path45 from "path";
5789
5943
  function isSupportFolder(value) {
5790
5944
  return value === "utils" || value === "types" || value === "schemas" || value === "constants";
5791
5945
  }
@@ -5818,7 +5972,7 @@ var rootSupportPlacementRule = {
5818
5972
  },
5819
5973
  create(context) {
5820
5974
  const sourceRoot = sourceRootOf(context);
5821
- const file = path44.resolve(context.filename);
5975
+ const file = path45.resolve(context.filename);
5822
5976
  const segments = segmentsOf(file, sourceRoot);
5823
5977
  const folderSegments = folderSegmentsOf(file, sourceRoot);
5824
5978
  const supportFolder = folderSegments[folderSegments.length - 1];
@@ -5858,7 +6012,7 @@ var rootSupportPlacementRule = {
5858
6012
  };
5859
6013
 
5860
6014
  // eslint/rules/route-handler-shape.ts
5861
- import path45 from "path";
6015
+ import path46 from "path";
5862
6016
  import ts7 from "typescript";
5863
6017
  var HTTP_METHODS2 = /* @__PURE__ */ new Set(["GET", "POST", "PUT", "PATCH", "DELETE", "HEAD", "OPTIONS"]);
5864
6018
  var REQUIRED_BOUNDARY = "withResponse";
@@ -5943,7 +6097,7 @@ var routeHandlerShapeRule = {
5943
6097
  }
5944
6098
  },
5945
6099
  create(context) {
5946
- if (path45.basename(context.filename) !== "route.ts") return {};
6100
+ if (path46.basename(context.filename) !== "route.ts") return {};
5947
6101
  const sourceText = context.sourceCode.text;
5948
6102
  function reportUnwrapped(node, name) {
5949
6103
  context.report({
@@ -6002,7 +6156,7 @@ var routeHandlerShapeRule = {
6002
6156
  };
6003
6157
 
6004
6158
  // eslint/rules/schema-casing.ts
6005
- import path46 from "path";
6159
+ import path47 from "path";
6006
6160
  function isCamelCase(name) {
6007
6161
  return /^[a-z][a-zA-Z0-9]*$/.test(name);
6008
6162
  }
@@ -6030,9 +6184,9 @@ var schemaCasingRule = {
6030
6184
  }
6031
6185
  },
6032
6186
  create(context) {
6033
- const filename = path46.resolve(context.filename);
6187
+ const filename = path47.resolve(context.filename);
6034
6188
  const sourceRoot = sourceRootOf(context);
6035
- if (!filename.startsWith(sourceRoot + path46.sep)) return {};
6189
+ if (!filename.startsWith(sourceRoot + path47.sep)) return {};
6036
6190
  let zodLocalName;
6037
6191
  return {
6038
6192
  ImportDeclaration(node) {
@@ -6064,7 +6218,7 @@ var schemaCasingRule = {
6064
6218
  };
6065
6219
 
6066
6220
  // eslint/rules/sole-state-owner.ts
6067
- import path47 from "path";
6221
+ import path48 from "path";
6068
6222
  import ts8 from "typescript";
6069
6223
  function findStateHooks(node) {
6070
6224
  const hooks = [];
@@ -6144,7 +6298,7 @@ var soleStateOwnerRule = {
6144
6298
  }
6145
6299
  },
6146
6300
  create(context) {
6147
- const filename = path47.resolve(context.filename);
6301
+ const filename = path48.resolve(context.filename);
6148
6302
  if (!filename.endsWith(".tsx") && !filename.endsWith(".jsx")) return {};
6149
6303
  const text = context.sourceCode.text;
6150
6304
  const components = parseComponentInfo(text, filename);
@@ -6223,7 +6377,7 @@ function usesOutsideJsx(declaration, hook, children) {
6223
6377
  }
6224
6378
 
6225
6379
  // eslint/rules/source-under-src.ts
6226
- import path48 from "path";
6380
+ import path49 from "path";
6227
6381
  var NON_SOURCE_ROOT_DIRS = /* @__PURE__ */ new Set([
6228
6382
  ".agents",
6229
6383
  ".cache",
@@ -6264,14 +6418,14 @@ var sourceUnderSrcRule = {
6264
6418
  }
6265
6419
  },
6266
6420
  create(context) {
6267
- const filename = path48.resolve(context.filename);
6421
+ const filename = path49.resolve(context.filename);
6268
6422
  if (!MODULE_EXTENSION.test(filename)) return {};
6269
- const relative = path48.relative(context.cwd, filename).replace(/\\/g, "/");
6423
+ const relative = path49.relative(context.cwd, filename).replace(/\\/g, "/");
6270
6424
  if (relative === "src" || relative.startsWith("src/")) return {};
6271
6425
  const topLevel = relative.split("/")[0] ?? "";
6272
6426
  if (NON_SOURCE_ROOT_DIRS.has(topLevel)) return {};
6273
6427
  if (!relative.includes("/")) {
6274
- const basename = path48.basename(filename);
6428
+ const basename = path49.basename(filename);
6275
6429
  if (CONFIG_FILE.test(basename) || DECLARATION_FILE.test(basename) || basename.startsWith(".")) return {};
6276
6430
  }
6277
6431
  return {
@@ -6287,7 +6441,7 @@ var sourceUnderSrcRule = {
6287
6441
  };
6288
6442
 
6289
6443
  // eslint/rules/stay-flat.ts
6290
- import path49 from "path";
6444
+ import path50 from "path";
6291
6445
  var stayFlatRule = {
6292
6446
  meta: {
6293
6447
  schema: [],
@@ -6298,7 +6452,7 @@ var stayFlatRule = {
6298
6452
  },
6299
6453
  create(context) {
6300
6454
  const sourceRoot = sourceRootOf(context);
6301
- const file = path49.resolve(context.filename);
6455
+ const file = path50.resolve(context.filename);
6302
6456
  const segments = segmentsOf(file, sourceRoot);
6303
6457
  if (segments.length !== 3 || segments[0] !== "features") return {};
6304
6458
  const index = getProjectIndex(sourceRoot);
@@ -6338,7 +6492,7 @@ var stayFlatRule = {
6338
6492
  };
6339
6493
 
6340
6494
  // eslint/rules/support-file-placement.ts
6341
- import path50 from "path";
6495
+ import path51 from "path";
6342
6496
  var CONFIG_OWNED_FOLDERS = /* @__PURE__ */ new Set(["types", "constants"]);
6343
6497
  var EXPORT_KIND_BY_SUPPORT_FOLDER = /* @__PURE__ */ new Map([
6344
6498
  ["constants", "constant"],
@@ -6363,7 +6517,7 @@ var supportFilePlacementRule = {
6363
6517
  },
6364
6518
  create(context) {
6365
6519
  const sourceRoot = sourceRootOf(context);
6366
- const supportFile = path50.resolve(context.filename);
6520
+ const supportFile = path51.resolve(context.filename);
6367
6521
  const currentFolder = folderSegmentsOf(supportFile, sourceRoot);
6368
6522
  const supportFolder = currentFolder[currentFolder.length - 1];
6369
6523
  if (supportFolder === void 0 || !SUPPORT_FOLDERS.has(supportFolder)) return {};
@@ -6417,7 +6571,7 @@ var supportFilePlacementRule = {
6417
6571
 
6418
6572
  // eslint/rules/support-folder-shape.ts
6419
6573
  import fs6 from "fs";
6420
- import path51 from "path";
6574
+ import path52 from "path";
6421
6575
  var SUPPORT_FOLDERS4 = /* @__PURE__ */ new Set(["constants", "types", "schemas"]);
6422
6576
  var INDEX_NAMES2 = /* @__PURE__ */ new Set(["index.ts", "index.tsx", "index.mts", "index.cts"]);
6423
6577
  var supportFolderShapeRule = {
@@ -6429,12 +6583,12 @@ var supportFolderShapeRule = {
6429
6583
  }
6430
6584
  },
6431
6585
  create(context) {
6432
- const filename = path51.resolve(context.filename);
6433
- const baseName = path51.basename(filename);
6586
+ const filename = path52.resolve(context.filename);
6587
+ const baseName = path52.basename(filename);
6434
6588
  if (!INDEX_NAMES2.has(baseName)) return {};
6435
- const folder = path51.basename(path51.dirname(filename));
6589
+ const folder = path52.basename(path52.dirname(filename));
6436
6590
  if (!SUPPORT_FOLDERS4.has(folder)) return {};
6437
- const directory = path51.dirname(filename);
6591
+ const directory = path52.dirname(filename);
6438
6592
  let entries;
6439
6593
  try {
6440
6594
  entries = fs6.readdirSync(directory);
@@ -6452,7 +6606,7 @@ var supportFolderShapeRule = {
6452
6606
  for (const match of source.matchAll(exportPattern)) {
6453
6607
  hasAnyReExport = true;
6454
6608
  const specifier = match.groups?.specifier;
6455
- if (specifier?.startsWith(".")) exportedFiles.add(path51.basename(specifier));
6609
+ if (specifier?.startsWith(".")) exportedFiles.add(path52.basename(specifier));
6456
6610
  }
6457
6611
  const guide = `docs/next-codebase-guide/rules/${folder === "constants" ? "constants" : "types-and-schemas"}-rule.md`;
6458
6612
  if (siblingModules.length === 0) {
@@ -6631,11 +6785,11 @@ var baseLayerPairRule = {
6631
6785
 
6632
6786
  // eslint/rules/tailwind/css-entry-point.ts
6633
6787
  import { statSync as statSync4 } from "fs";
6634
- import path54 from "path";
6788
+ import path55 from "path";
6635
6789
 
6636
6790
  // eslint/rules/tailwind/source-files.ts
6637
6791
  import { readdirSync as readdirSync3, readFileSync as readFileSync9, statSync as statSync3 } from "fs";
6638
- import path52 from "path";
6792
+ import path53 from "path";
6639
6793
  var CSS_EXTENSIONS = [".css"];
6640
6794
  var MODULE_EXTENSIONS4 = [".ts", ".tsx", ".mts", ".cts", ".js", ".jsx", ".mjs", ".cjs"];
6641
6795
  var SOURCE_EXTENSIONS = [...MODULE_EXTENSIONS4, ...CSS_EXTENSIONS];
@@ -6648,7 +6802,7 @@ function findFiles(dir, extensions) {
6648
6802
  }
6649
6803
  return entries.flatMap((entry) => {
6650
6804
  if (entry.startsWith(".") || entry === "node_modules") return [];
6651
- const entryPath = path52.join(dir, entry);
6805
+ const entryPath = path53.join(dir, entry);
6652
6806
  let stats;
6653
6807
  try {
6654
6808
  stats = statSync3(entryPath);
@@ -6656,7 +6810,7 @@ function findFiles(dir, extensions) {
6656
6810
  return [];
6657
6811
  }
6658
6812
  if (stats.isDirectory()) return findFiles(entryPath, extensions);
6659
- return extensions.includes(path52.extname(entry)) ? [entryPath] : [];
6813
+ return extensions.includes(path53.extname(entry)) ? [entryPath] : [];
6660
6814
  });
6661
6815
  }
6662
6816
  function cachedTextReader() {
@@ -6679,7 +6833,7 @@ function escapeRegExp(text) {
6679
6833
  }
6680
6834
 
6681
6835
  // eslint/rules/tailwind/stylesheet-graph.ts
6682
- import path53 from "path";
6836
+ import path54 from "path";
6683
6837
  function registersTailwind(text) {
6684
6838
  return /@import\s+(?:url\(\s*)?["']tailwindcss["']\s*\)?/i.test(text);
6685
6839
  }
@@ -6693,25 +6847,25 @@ function moduleImports(text, fileName) {
6693
6847
  return new RegExp(`(?:import|require)\\s*\\(?\\s*["'][^"']*${escaped}["']`, "i").test(text);
6694
6848
  }
6695
6849
  function resolveSpecifier2(fromFile, spec, sourceRoot) {
6696
- if (spec.startsWith("/")) return path53.resolve(spec);
6697
- if (spec.startsWith("./") || spec.startsWith("../")) return path53.resolve(path53.dirname(fromFile), spec);
6698
- if (spec.startsWith("@/")) return path53.resolve(sourceRoot, spec.slice(2));
6850
+ if (spec.startsWith("/")) return path54.resolve(spec);
6851
+ if (spec.startsWith("./") || spec.startsWith("../")) return path54.resolve(path54.dirname(fromFile), spec);
6852
+ if (spec.startsWith("@/")) return path54.resolve(sourceRoot, spec.slice(2));
6699
6853
  return void 0;
6700
6854
  }
6701
6855
  function buildStylesheetGraph(options) {
6702
6856
  const { cssFiles, sourceRoot, textOf } = options;
6703
- const cssSet = new Set(cssFiles.map((file) => path53.normalize(file)));
6857
+ const cssSet = new Set(cssFiles.map((file) => path54.normalize(file)));
6704
6858
  const globals = cssFiles.filter((file) => registersTailwind(textOf(file)));
6705
6859
  const reachable = /* @__PURE__ */ new Set();
6706
6860
  const queue = [...globals];
6707
- for (const global of globals) reachable.add(path53.normalize(global));
6861
+ for (const global of globals) reachable.add(path54.normalize(global));
6708
6862
  while (queue.length > 0) {
6709
6863
  const from = queue.shift();
6710
6864
  if (!from) continue;
6711
6865
  for (const spec of importedSpecifiers(textOf(from))) {
6712
6866
  const target = resolveSpecifier2(from, spec, sourceRoot);
6713
6867
  if (!target) continue;
6714
- const normalized = path53.normalize(target);
6868
+ const normalized = path54.normalize(target);
6715
6869
  if (cssSet.has(normalized) && !reachable.has(normalized)) {
6716
6870
  reachable.add(normalized);
6717
6871
  queue.push(normalized);
@@ -6723,7 +6877,7 @@ function buildStylesheetGraph(options) {
6723
6877
  for (const spec of importedSpecifiers(textOf(global))) {
6724
6878
  const target = resolveSpecifier2(global, spec, sourceRoot);
6725
6879
  if (!target) continue;
6726
- const normalized = path53.normalize(target);
6880
+ const normalized = path54.normalize(target);
6727
6881
  if (cssSet.has(normalized)) directChildren.add(normalized);
6728
6882
  }
6729
6883
  }
@@ -6731,8 +6885,8 @@ function buildStylesheetGraph(options) {
6731
6885
  }
6732
6886
 
6733
6887
  // eslint/rules/tailwind/css-entry-point.ts
6734
- var APP_STYLES_DIR = path54.join("app", "styles");
6735
- var GLOBAL_STYLESHEET_PATH = path54.join(APP_STYLES_DIR, "globals.css");
6888
+ var APP_STYLES_DIR = path55.join("app", "styles");
6889
+ var GLOBAL_STYLESHEET_PATH = path55.join(APP_STYLES_DIR, "globals.css");
6736
6890
  var cssEntryPointRule = {
6737
6891
  meta: {
6738
6892
  schema: [],
@@ -6758,8 +6912,8 @@ var cssEntryPointRule = {
6758
6912
  return {
6759
6913
  "StyleSheet:exit"(node) {
6760
6914
  if (globals.length === 0) return;
6761
- const current = path54.normalize(path54.resolve(context.filename));
6762
- const relative = path54.relative(sourceRoot, current);
6915
+ const current = path55.normalize(path55.resolve(context.filename));
6916
+ const relative = path55.relative(sourceRoot, current);
6763
6917
  if (globals.includes(current)) {
6764
6918
  if (globals.length > 1) {
6765
6919
  context.report({
@@ -6775,7 +6929,7 @@ var cssEntryPointRule = {
6775
6929
  });
6776
6930
  return;
6777
6931
  }
6778
- const basename = path54.basename(current);
6932
+ const basename = path55.basename(current);
6779
6933
  const importCount = moduleFiles.filter((modulePath) => moduleImports(textOf(modulePath), basename)).length;
6780
6934
  if (importCount !== 1) {
6781
6935
  context.report({
@@ -6785,7 +6939,7 @@ var cssEntryPointRule = {
6785
6939
  }
6786
6940
  return;
6787
6941
  }
6788
- const isInAppStyles = relative === APP_STYLES_DIR || relative.startsWith(`${APP_STYLES_DIR}${path54.sep}`);
6942
+ const isInAppStyles = relative === APP_STYLES_DIR || relative.startsWith(`${APP_STYLES_DIR}${path55.sep}`);
6789
6943
  if (!isInAppStyles) {
6790
6944
  context.report({
6791
6945
  node,
@@ -7274,7 +7428,7 @@ var tailwindRules = {
7274
7428
  };
7275
7429
 
7276
7430
  // eslint/rules/type-extraction.ts
7277
- import path55 from "path";
7431
+ import path56 from "path";
7278
7432
  var typeExtractionRule = {
7279
7433
  meta: {
7280
7434
  schema: [],
@@ -7285,7 +7439,7 @@ var typeExtractionRule = {
7285
7439
  },
7286
7440
  create(context) {
7287
7441
  const sourceRoot = sourceRootOf(context);
7288
- const file = path55.resolve(context.filename);
7442
+ const file = path56.resolve(context.filename);
7289
7443
  const segments = segmentsOf(file, sourceRoot);
7290
7444
  if (segments.length === 0) return {};
7291
7445
  const index = getProjectIndex(sourceRoot);
@@ -7420,7 +7574,7 @@ var uiStateRule = {
7420
7574
  // eslint/rules/unknown-utility.ts
7421
7575
  import { existsSync as existsSync6, readdirSync as readdirSync4, readFileSync as readFileSync10, statSync as statSync6 } from "fs";
7422
7576
  import { createRequire } from "module";
7423
- import path56 from "path";
7577
+ import path57 from "path";
7424
7578
  var PREFIX_NAMESPACES = {
7425
7579
  bg: ["color"],
7426
7580
  text: ["color", "text"],
@@ -7660,7 +7814,7 @@ function stylesheetFiles(dir) {
7660
7814
  }
7661
7815
  return entries.flatMap((entry) => {
7662
7816
  if (entry.startsWith(".") || entry === "node_modules") return [];
7663
- const entryPath = path56.join(dir, entry);
7817
+ const entryPath = path57.join(dir, entry);
7664
7818
  let stats;
7665
7819
  try {
7666
7820
  stats = statSync6(entryPath);
@@ -7668,7 +7822,7 @@ function stylesheetFiles(dir) {
7668
7822
  return [];
7669
7823
  }
7670
7824
  if (stats.isDirectory()) return stylesheetFiles(entryPath);
7671
- return path56.extname(entry) === ".css" ? [entryPath] : [];
7825
+ return path57.extname(entry) === ".css" ? [entryPath] : [];
7672
7826
  });
7673
7827
  }
7674
7828
  function packageNameOf(specifier) {
@@ -7679,10 +7833,10 @@ function packageNameOf(specifier) {
7679
7833
  function resolvePackageStylesheet(fromFile, specifier) {
7680
7834
  const packageName = packageNameOf(specifier);
7681
7835
  if (!packageName || packageName === "tailwindcss") return void 0;
7682
- let directory = path56.dirname(fromFile);
7683
- while (directory !== path56.dirname(directory)) {
7684
- const packageRoot = path56.join(directory, "node_modules", packageName);
7685
- const manifestPath = path56.join(packageRoot, "package.json");
7836
+ let directory = path57.dirname(fromFile);
7837
+ while (directory !== path57.dirname(directory)) {
7838
+ const packageRoot = path57.join(directory, "node_modules", packageName);
7839
+ const manifestPath = path57.join(packageRoot, "package.json");
7686
7840
  if (existsSync6(manifestPath)) {
7687
7841
  try {
7688
7842
  const manifest = readFileSync10(manifestPath, "utf8");
@@ -7690,13 +7844,13 @@ function resolvePackageStylesheet(fromFile, specifier) {
7690
7844
  const main = /"main"\s*:\s*"(?<file>[^"]+\.css)"/.exec(manifest)?.groups?.file;
7691
7845
  const target = stylesheet ?? main;
7692
7846
  if (!target) return void 0;
7693
- const resolved = path56.resolve(packageRoot, target);
7847
+ const resolved = path57.resolve(packageRoot, target);
7694
7848
  return existsSync6(resolved) ? resolved : void 0;
7695
7849
  } catch {
7696
7850
  return void 0;
7697
7851
  }
7698
7852
  }
7699
- directory = path56.dirname(directory);
7853
+ directory = path57.dirname(directory);
7700
7854
  }
7701
7855
  return void 0;
7702
7856
  }
@@ -7947,7 +8101,7 @@ var unknownUtilityRule = {
7947
8101
  };
7948
8102
 
7949
8103
  // eslint/rules/util-file-name.ts
7950
- import path57 from "path";
8104
+ import path58 from "path";
7951
8105
  function toKebabCase2(value) {
7952
8106
  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();
7953
8107
  }
@@ -7960,7 +8114,7 @@ var utilFileNameRule = {
7960
8114
  }
7961
8115
  },
7962
8116
  create(context) {
7963
- const filename = path57.resolve(context.filename);
8117
+ const filename = path58.resolve(context.filename);
7964
8118
  const segments = filename.replace(/\\/g, "/").split("/");
7965
8119
  if (!segments.includes("utils")) return {};
7966
8120
  let module;
@@ -7974,13 +8128,13 @@ var utilFileNameRule = {
7974
8128
  const functionName = functions[0]?.name;
7975
8129
  if (!functionName) return {};
7976
8130
  const expected = toKebabCase2(functionName);
7977
- const actual = path57.basename(filename, path57.extname(filename));
8131
+ const actual = path58.basename(filename, path58.extname(filename));
7978
8132
  if (!expected || actual === expected) return {};
7979
8133
  return {
7980
8134
  Program(node) {
7981
8135
  context.report({
7982
8136
  node,
7983
- message: `A utility file exporting ${functionName} must be named ${expected}.${path57.extname(filename).slice(1)}.`
8137
+ message: `A utility file exporting ${functionName} must be named ${expected}.${path58.extname(filename).slice(1)}.`
7984
8138
  });
7985
8139
  }
7986
8140
  };
@@ -7988,7 +8142,7 @@ var utilFileNameRule = {
7988
8142
  };
7989
8143
 
7990
8144
  // eslint/rules/value-extraction.ts
7991
- import path58 from "path";
8145
+ import path59 from "path";
7992
8146
  var valueExtractionRule = {
7993
8147
  meta: {
7994
8148
  schema: [],
@@ -7999,7 +8153,7 @@ var valueExtractionRule = {
7999
8153
  },
8000
8154
  create(context) {
8001
8155
  const sourceRoot = sourceRootOf(context);
8002
- const file = path58.resolve(context.filename);
8156
+ const file = path59.resolve(context.filename);
8003
8157
  const segments = segmentsOf(file, sourceRoot);
8004
8158
  if (segments.length === 0 || segments[0] !== "app") return {};
8005
8159
  const index = getProjectIndex(sourceRoot);
@@ -8021,7 +8175,7 @@ var valueExtractionRule = {
8021
8175
 
8022
8176
  // eslint/rules/vulyk/tracked-docs.ts
8023
8177
  import { existsSync as existsSync7, readFileSync as readFileSync11 } from "fs";
8024
- import path59 from "path";
8178
+ import path60 from "path";
8025
8179
  var PASIKA_REPO = "Bredansky/pasika";
8026
8180
  var BASE_REQUIRED_TRACKED_DOCS = [
8027
8181
  { name: "documentation-guide", path: "docs/documentation-guide" },
@@ -8054,8 +8208,8 @@ var trackedDocsRule = {
8054
8208
  if (!context.filename.endsWith("package.json")) return;
8055
8209
  const root = node.body;
8056
8210
  if (root.type !== "Object") return;
8057
- const projectRoot = path59.dirname(path59.resolve(context.filename));
8058
- const configPath = path59.join(projectRoot, "vulyk.config.ts");
8211
+ const projectRoot = path60.dirname(path60.resolve(context.filename));
8212
+ const configPath = path60.join(projectRoot, "vulyk.config.ts");
8059
8213
  if (!existsSync7(configPath)) {
8060
8214
  context.report({
8061
8215
  node,
@@ -8080,7 +8234,7 @@ var trackedDocsRule = {
8080
8234
  });
8081
8235
  }
8082
8236
  }
8083
- const agentsPath = path59.join(projectRoot, "AGENTS.md");
8237
+ const agentsPath = path60.join(projectRoot, "AGENTS.md");
8084
8238
  if (!existsSync7(agentsPath)) {
8085
8239
  context.report({
8086
8240
  node,
@@ -8139,12 +8293,12 @@ var vulykRules = {
8139
8293
  };
8140
8294
 
8141
8295
  // eslint/rules/with-response-helper.ts
8142
- var HELPER2 = "withResponse";
8143
- var ENTRY2 = "pasika/with-response";
8144
- var DOC4 = "docs/pasika-adoption-guide/rules/with-response-helper-rule.md";
8145
- var DECLARED2 = `A repository must not declare its own ${HELPER2}; import it from ${ENTRY2}. See ${DOC4}`;
8146
- var IMPORTED2 = `${HELPER2} must be imported from ${ENTRY2}. See ${DOC4}`;
8147
- function isNamed2(node, name) {
8296
+ var HELPER3 = "withResponse";
8297
+ var ENTRY3 = "pasika/with-response";
8298
+ var DOC5 = "docs/pasika-adoption-guide/rules/with-response-helper-rule.md";
8299
+ var DECLARED3 = `A repository must not declare its own ${HELPER3}; import it from ${ENTRY3}. See ${DOC5}`;
8300
+ var IMPORTED3 = `${HELPER3} must be imported from ${ENTRY3}. See ${DOC5}`;
8301
+ function isNamed3(node, name) {
8148
8302
  return node?.type === "Identifier" && node.name === name;
8149
8303
  }
8150
8304
  var withResponseHelperRule = {
@@ -8152,24 +8306,24 @@ var withResponseHelperRule = {
8152
8306
  schema: [],
8153
8307
  type: "problem",
8154
8308
  docs: {
8155
- description: `Require ${HELPER2} to be imported from ${ENTRY2} rather than declared in the repository.`
8309
+ description: `Require ${HELPER3} to be imported from ${ENTRY3} rather than declared in the repository.`
8156
8310
  }
8157
8311
  },
8158
8312
  create(context) {
8159
8313
  const checkSource = (node) => {
8160
- if (!node.source || node.source.value === ENTRY2) return;
8314
+ if (!node.source || node.source.value === ENTRY3) return;
8161
8315
  for (const specifier of node.specifiers) {
8162
- if (!isNamed2(specifier.local, HELPER2)) continue;
8163
- context.report({ node: specifier, message: IMPORTED2 });
8316
+ if (!isNamed3(specifier.local, HELPER3)) continue;
8317
+ context.report({ node: specifier, message: IMPORTED3 });
8164
8318
  }
8165
8319
  };
8166
8320
  return {
8167
8321
  FunctionDeclaration(node) {
8168
- if (isNamed2(node.id, HELPER2)) context.report({ node, message: DECLARED2 });
8322
+ if (isNamed3(node.id, HELPER3)) context.report({ node, message: DECLARED3 });
8169
8323
  },
8170
8324
  VariableDeclarator(node) {
8171
- if (isNamed2(node.id.type === "Identifier" ? node.id : null, HELPER2)) {
8172
- context.report({ node, message: DECLARED2 });
8325
+ if (isNamed3(node.id.type === "Identifier" ? node.id : null, HELPER3)) {
8326
+ context.report({ node, message: DECLARED3 });
8173
8327
  }
8174
8328
  },
8175
8329
  ImportDeclaration: checkSource,
@@ -8180,7 +8334,7 @@ var withResponseHelperRule = {
8180
8334
 
8181
8335
  // eslint/rules/zirka-baseline.ts
8182
8336
  import fs7 from "fs";
8183
- import path60 from "path";
8337
+ import path61 from "path";
8184
8338
  var ESLINT_CONFIG = /^eslint\.config\.(?:ts|mts|cts|js|mjs|cjs)$/;
8185
8339
  var PRETTIER_CONFIGS = [
8186
8340
  "prettier.config.mjs",
@@ -8199,10 +8353,10 @@ var zirkaBaselineRule = {
8199
8353
  }
8200
8354
  },
8201
8355
  create(context) {
8202
- const filename = path60.resolve(context.filename);
8203
- const basename = path60.basename(filename);
8356
+ const filename = path61.resolve(context.filename);
8357
+ const basename = path61.basename(filename);
8204
8358
  if (!ESLINT_CONFIG.test(basename)) return {};
8205
- const projectRoot = path60.dirname(filename);
8359
+ const projectRoot = path61.dirname(filename);
8206
8360
  const report3 = (message) => {
8207
8361
  context.report({
8208
8362
  node: context.sourceCode.ast,
@@ -8217,7 +8371,7 @@ var zirkaBaselineRule = {
8217
8371
  'ESLint config must take its configuration from zirka (import { styleguide } from "zirka") instead of restating rules locally.'
8218
8372
  );
8219
8373
  }
8220
- const tsconfigPath = path60.join(projectRoot, "tsconfig.json");
8374
+ const tsconfigPath = path61.join(projectRoot, "tsconfig.json");
8221
8375
  if (!fs7.existsSync(tsconfigPath)) {
8222
8376
  report3('No tsconfig.json found. Create one extending the zirka TypeScript base config ("zirka/typescript").');
8223
8377
  } else {
@@ -8235,13 +8389,13 @@ var zirkaBaselineRule = {
8235
8389
  report3('tsconfig.json must extend the zirka TypeScript base config ("zirka/typescript").');
8236
8390
  }
8237
8391
  }
8238
- const prettierConfigFile = PRETTIER_CONFIGS.find((name) => fs7.existsSync(path60.join(projectRoot, name)));
8392
+ const prettierConfigFile = PRETTIER_CONFIGS.find((name) => fs7.existsSync(path61.join(projectRoot, name)));
8239
8393
  if (!prettierConfigFile) {
8240
8394
  report3(
8241
8395
  "No prettier config found. Create one that takes its configuration from zirka (styleguide({ prettier: true }).prettierConfig)."
8242
8396
  );
8243
8397
  } else {
8244
- const content = fs7.readFileSync(path60.join(projectRoot, prettierConfigFile), "utf8");
8398
+ const content = fs7.readFileSync(path61.join(projectRoot, prettierConfigFile), "utf8");
8245
8399
  if (!content.includes("zirka")) {
8246
8400
  report3(
8247
8401
  "The prettier config must take its configuration from zirka (styleguide({ prettier: true }).prettierConfig) instead of restating it locally."
@@ -8262,36 +8416,36 @@ function referencesZirka(sourceCode) {
8262
8416
  }
8263
8417
 
8264
8418
  // eslint/rules/zod-fetch-helper.ts
8265
- var HELPER3 = "zodFetch";
8266
- var ENTRY3 = "pasika/zod-fetch";
8267
- var DOC5 = "docs/pasika-adoption-guide/rules/zod-fetch-helper-rule.md";
8268
- var FETCHED = `fetch must not be called; make the request through ${HELPER3} from ${ENTRY3}. See ${DOC5}`;
8269
- var DECLARED3 = `A file must not declare its own ${HELPER3}; import it from ${ENTRY3}. See ${DOC5}`;
8270
- var IMPORTED3 = `${HELPER3} must be imported from ${ENTRY3}. See ${DOC5}`;
8419
+ var HELPER4 = "zodFetch";
8420
+ var ENTRY4 = "pasika/zod-fetch";
8421
+ var DOC6 = "docs/pasika-adoption-guide/rules/zod-fetch-helper-rule.md";
8422
+ var FETCHED = `fetch must not be called; make the request through ${HELPER4} from ${ENTRY4}. See ${DOC6}`;
8423
+ var DECLARED4 = `A file must not declare its own ${HELPER4}; import it from ${ENTRY4}. See ${DOC6}`;
8424
+ var IMPORTED4 = `${HELPER4} must be imported from ${ENTRY4}. See ${DOC6}`;
8271
8425
  var GLOBAL_OBJECTS = /* @__PURE__ */ new Set(["globalThis", "window", "self", "global"]);
8272
- var TEST_FILE = /(?:^|[\\/])(?:__tests__|tests)[\\/]|[.](?:test|spec)[.][cm]?[jt]sx?$/;
8273
- function isNamed3(node, name) {
8426
+ var TEST_FILE2 = /(?:^|[\\/])(?:__tests__|tests)[\\/]|[.](?:test|spec)[.][cm]?[jt]sx?$/;
8427
+ function isNamed4(node, name) {
8274
8428
  return node?.type === "Identifier" && node.name === name;
8275
8429
  }
8276
8430
  function callsFetch(callee) {
8277
- if (isNamed3(callee, "fetch")) return true;
8278
- return callee.type === "MemberExpression" && !callee.computed && isNamed3(callee.property, "fetch") && callee.object.type === "Identifier" && GLOBAL_OBJECTS.has(callee.object.name);
8431
+ if (isNamed4(callee, "fetch")) return true;
8432
+ return callee.type === "MemberExpression" && !callee.computed && isNamed4(callee.property, "fetch") && callee.object.type === "Identifier" && GLOBAL_OBJECTS.has(callee.object.name);
8279
8433
  }
8280
8434
  var zodFetchHelperRule = {
8281
8435
  meta: {
8282
8436
  schema: [],
8283
8437
  type: "problem",
8284
8438
  docs: {
8285
- description: `Require every request to go through the ${HELPER3} imported from ${ENTRY3}, the only caller of fetch.`
8439
+ description: `Require every request to go through the ${HELPER4} imported from ${ENTRY4}, the only caller of fetch.`
8286
8440
  }
8287
8441
  },
8288
8442
  create(context) {
8289
- if (TEST_FILE.test(context.filename)) return {};
8443
+ if (TEST_FILE2.test(context.filename)) return {};
8290
8444
  const checkSource = (node) => {
8291
- if (!node.source || node.source.value === ENTRY3) return;
8445
+ if (!node.source || node.source.value === ENTRY4) return;
8292
8446
  for (const specifier of node.specifiers) {
8293
- if (!isNamed3(specifier.local, HELPER3)) continue;
8294
- context.report({ node: specifier, message: IMPORTED3 });
8447
+ if (!isNamed4(specifier.local, HELPER4)) continue;
8448
+ context.report({ node: specifier, message: IMPORTED4 });
8295
8449
  }
8296
8450
  };
8297
8451
  return {
@@ -8300,11 +8454,11 @@ var zodFetchHelperRule = {
8300
8454
  context.report({ node, message: FETCHED });
8301
8455
  },
8302
8456
  FunctionDeclaration(node) {
8303
- if (isNamed3(node.id, HELPER3)) context.report({ node, message: DECLARED3 });
8457
+ if (isNamed4(node.id, HELPER4)) context.report({ node, message: DECLARED4 });
8304
8458
  },
8305
8459
  VariableDeclarator(node) {
8306
- if (isNamed3(node.id.type === "Identifier" ? node.id : null, HELPER3)) {
8307
- context.report({ node, message: DECLARED3 });
8460
+ if (isNamed4(node.id.type === "Identifier" ? node.id : null, HELPER4)) {
8461
+ context.report({ node, message: DECLARED4 });
8308
8462
  }
8309
8463
  },
8310
8464
  ImportDeclaration: checkSource,
@@ -8436,6 +8590,7 @@ function assertTypescriptAlignment() {
8436
8590
  // eslint/index.ts
8437
8591
  var pasikaNextjsAppRules = {
8438
8592
  // Framework-agnostic TypeScript rules.
8593
+ "api-contract": apiContractRule,
8439
8594
  "file-length": fileLengthRule,
8440
8595
  "filename-case": filenameCaseRule,
8441
8596
  "import-boundaries": importBoundariesRule,