pasika 0.10.56 → 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.
- package/README.md +10 -8
- package/dist/chunk-Z3C5YVO4.js +13 -0
- package/dist/eslint/pasika/index.d.ts +1 -0
- package/dist/eslint/pasika/index.js +453 -299
- package/dist/helpers/api-contract.d.ts +20 -0
- package/dist/helpers/api-contract.js +8 -0
- package/dist/helpers/with-response.d.ts +7 -8
- package/dist/helpers/with-response.js +11 -8
- package/dist/helpers/zod-fetch.d.ts +15 -17
- package/dist/helpers/zod-fetch.js +24 -16
- package/package.json +5 -5
- package/dist/helpers/response-envelope.d.ts +0 -20
- package/dist/helpers/response-envelope.js +0 -18
|
@@ -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
|
|
162
|
+
import path5 from "path";
|
|
10
163
|
|
|
11
164
|
// eslint/project/ccf.ts
|
|
12
165
|
import fs from "fs";
|
|
13
|
-
import
|
|
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 =
|
|
17
|
-
return relative.startsWith("..") ? [] : relative.split(
|
|
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 =
|
|
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) =>
|
|
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
|
|
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:
|
|
401
|
+
return { file: path3.resolve(file), imports, reexports, exports };
|
|
249
402
|
}
|
|
250
403
|
|
|
251
404
|
// eslint/rules/project-root.ts
|
|
252
|
-
import
|
|
405
|
+
import path4 from "path";
|
|
253
406
|
function sourceRootOf(context) {
|
|
254
|
-
return
|
|
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(
|
|
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
|
|
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 =
|
|
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 =
|
|
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(
|
|
542
|
+
if (moduleRoot && !fs2.existsSync(path5.join(moduleRoot, "index.ts"))) {
|
|
390
543
|
return report(
|
|
391
544
|
context,
|
|
392
|
-
`Add src/config/${
|
|
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 &&
|
|
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/${
|
|
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 =
|
|
408
|
-
const currentFolder2 =
|
|
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) &&
|
|
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) ||
|
|
574
|
+
if (ROUTING_FILES.has(basename) || path5.extname(filename) === ".css") return {};
|
|
422
575
|
}
|
|
423
|
-
const currentFolder =
|
|
576
|
+
const currentFolder = path5.basename(path5.dirname(filename));
|
|
424
577
|
const kinds = exportedKinds(filename);
|
|
425
|
-
const isConfigModuleRoot = topLevel === "config" && segments.length === 3 &&
|
|
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 ${
|
|
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
|
|
466
|
-
var
|
|
467
|
-
var
|
|
468
|
-
var
|
|
469
|
-
var
|
|
470
|
-
function
|
|
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 ${
|
|
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 ===
|
|
636
|
+
if (!node.source || node.source.value === ENTRY2) return;
|
|
484
637
|
for (const specifier of node.specifiers) {
|
|
485
|
-
if (!
|
|
486
|
-
context.report({ node: specifier, message:
|
|
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 (
|
|
644
|
+
if (isNamed2(node.id, HELPER2)) context.report({ node, message: DECLARED2 });
|
|
492
645
|
},
|
|
493
646
|
VariableDeclarator(node) {
|
|
494
|
-
if (
|
|
495
|
-
context.report({ node, message:
|
|
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
|
|
658
|
+
import path7 from "path";
|
|
506
659
|
|
|
507
660
|
// eslint/rules/component-conventions.ts
|
|
508
|
-
import
|
|
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(
|
|
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(
|
|
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 =
|
|
919
|
+
const filename = path7.resolve(context.filename);
|
|
767
920
|
const sourceRoot = sourceRootOf(context);
|
|
768
|
-
if (!filename.startsWith(sourceRoot +
|
|
769
|
-
if (
|
|
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
|
|
939
|
+
import path9 from "path";
|
|
787
940
|
|
|
788
941
|
// eslint/project/index.ts
|
|
789
942
|
import { readdirSync, statSync } from "fs";
|
|
790
|
-
import
|
|
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 =
|
|
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(
|
|
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 =
|
|
981
|
+
base = path8.resolve(sourceRoot, specifier.slice(2));
|
|
829
982
|
} else if (specifier.startsWith(".")) {
|
|
830
|
-
base =
|
|
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) =>
|
|
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 =
|
|
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
|
|
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(
|
|
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 =
|
|
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
|
|
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 =
|
|
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
|
|
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 =
|
|
1256
|
+
const filename = path12.resolve(context.filename);
|
|
1104
1257
|
const sourceRoot = sourceRootOf(context);
|
|
1105
|
-
if (!filename.startsWith(sourceRoot +
|
|
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
|
|
1280
|
+
import path13 from "path";
|
|
1128
1281
|
var FEATURES_SEGMENT = "features";
|
|
1129
1282
|
function featureNameOf(resolvedPath, sourceRoot) {
|
|
1130
|
-
const relative =
|
|
1283
|
+
const relative = path13.relative(sourceRoot, resolvedPath);
|
|
1131
1284
|
if (relative.startsWith("..")) return void 0;
|
|
1132
|
-
const segments = relative.split(
|
|
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 =
|
|
1301
|
+
const fileRelative = path13.relative(sourceRoot, filename);
|
|
1149
1302
|
if (fileRelative.startsWith("..")) return {};
|
|
1150
|
-
const fileSegments = fileRelative.split(
|
|
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 =
|
|
1318
|
+
resolved = path13.resolve(sourceRoot, source.value.slice(2));
|
|
1166
1319
|
} else if (source.value.startsWith(".")) {
|
|
1167
|
-
resolved =
|
|
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
|
|
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 =
|
|
1502
|
+
const filename = path14.resolve(context.filename);
|
|
1350
1503
|
if (!filename.endsWith(".tsx")) return {};
|
|
1351
|
-
const base =
|
|
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
|
|
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 =
|
|
1554
|
+
const base = path15.basename(filename);
|
|
1402
1555
|
return base === "AGENTS.md" || base === "CLAUDE.md";
|
|
1403
1556
|
}
|
|
1404
1557
|
function isDocumentationTemplate(filename) {
|
|
1405
|
-
return
|
|
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
|
|
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
|
|
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 =
|
|
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 =
|
|
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:
|
|
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 =
|
|
1681
|
+
let dir = path16.dirname(filePath);
|
|
1529
1682
|
for (; ; ) {
|
|
1530
|
-
if (
|
|
1683
|
+
if (path16.basename(dir) === "docs" && statSync2(dir).isDirectory()) {
|
|
1531
1684
|
return dir;
|
|
1532
1685
|
}
|
|
1533
|
-
const parent =
|
|
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
|
|
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 =
|
|
1635
|
-
const referencesDir =
|
|
1787
|
+
const guideDir = path17.dirname(filename);
|
|
1788
|
+
const referencesDir = path17.join(guideDir, "references");
|
|
1636
1789
|
const guideReferences = docs.filter(
|
|
1637
|
-
(doc) => doc.kind === "reference" &&
|
|
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
|
|
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
|
|
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(
|
|
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 =
|
|
1863
|
+
const currentDir = path18.dirname(filename);
|
|
1711
1864
|
if (guideFolders.has(currentDir)) {
|
|
1712
|
-
const expectedEntryPoint = `${
|
|
1865
|
+
const expectedEntryPoint = `${path18.basename(currentDir)}.md`;
|
|
1713
1866
|
const hasEntryPoint = docs.some(
|
|
1714
|
-
(doc) => doc.kind === "guide" &&
|
|
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
|
|
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 =
|
|
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
|
|
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 =
|
|
1855
|
-
if (
|
|
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 =
|
|
1859
|
-
return parent ===
|
|
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 =
|
|
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
|
|
2718
|
+
import path21 from "path";
|
|
2566
2719
|
function checkPlacement(filename, kind) {
|
|
2567
|
-
const parentFolder =
|
|
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 =
|
|
2573
|
-
const guideFolder =
|
|
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(
|
|
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
|
|
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 =
|
|
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
|
|
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 =
|
|
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 =
|
|
2863
|
+
const baseName = path23.basename(filename);
|
|
2711
2864
|
const isIndexFile = baseName === "index.ts";
|
|
2712
2865
|
if (!isIndexFile) return {};
|
|
2713
|
-
const dirPath =
|
|
2714
|
-
const folderName =
|
|
2715
|
-
const parentFolderName =
|
|
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
|
|
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(
|
|
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
|
|
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 =
|
|
3100
|
+
const filename = path25.resolve(context.filename);
|
|
2948
3101
|
const sourceRoot = sourceRootOf(context);
|
|
2949
|
-
if (!filename.startsWith(sourceRoot +
|
|
2950
|
-
if (
|
|
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
|
|
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 =
|
|
3035
|
-
let base =
|
|
3036
|
-
const baseExt =
|
|
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 =
|
|
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 "${
|
|
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 "${
|
|
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 "${
|
|
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 "${
|
|
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
|
|
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 =
|
|
3369
|
+
const relative = path27.relative(sourceRoot, filename);
|
|
3217
3370
|
if (relative.startsWith("..")) return {};
|
|
3218
|
-
const segments = relative.split(
|
|
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
|
|
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 =
|
|
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
|
|
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
|
|
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 ${
|
|
3350
|
-
var delegatedModuleMessage = (name) => `A delegated module must report a failure by throwing an HttpError, not "${name}". See ${
|
|
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(
|
|
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 =
|
|
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) =>
|
|
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 =
|
|
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
|
|
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 =
|
|
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 =
|
|
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
|
|
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
|
|
3708
|
+
return path31.resolve(sourceRoot, importPath.slice(2));
|
|
3556
3709
|
}
|
|
3557
3710
|
if (importPath.startsWith(".")) {
|
|
3558
|
-
return
|
|
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 =
|
|
3564
|
-
if (relativePath.startsWith("..") ||
|
|
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(
|
|
3720
|
+
return relativePath.split(path31.sep);
|
|
3568
3721
|
}
|
|
3569
3722
|
function relativeSpecifier(filename, resolvedPath) {
|
|
3570
|
-
const relativePath =
|
|
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 =
|
|
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
|
|
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 =
|
|
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 ||
|
|
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 = `${
|
|
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
|
|
3907
|
+
return path32.resolve(context.cwd ?? process.cwd(), "src");
|
|
3755
3908
|
}
|
|
3756
3909
|
|
|
3757
3910
|
// eslint/rules/interactive-component.ts
|
|
3758
|
-
import
|
|
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 =
|
|
3915
|
-
const base =
|
|
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
|
|
4192
|
+
import path34 from "path";
|
|
4040
4193
|
function isInLocalesDir(filename) {
|
|
4041
|
-
const segments =
|
|
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
|
|
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 =
|
|
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
|
|
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 =
|
|
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
|
|
4490
|
+
import path37 from "path";
|
|
4338
4491
|
function isLocalesFile2(filename) {
|
|
4339
|
-
const segments =
|
|
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 =
|
|
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
|
|
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(
|
|
4679
|
+
const normalized = filename.replaceAll(path38.sep, "/");
|
|
4527
4680
|
if (!normalized.includes("/src/app/")) return false;
|
|
4528
|
-
const basename =
|
|
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
|
|
4792
|
-
var
|
|
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. ${
|
|
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 =
|
|
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 =
|
|
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
|
|
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 =
|
|
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 || !
|
|
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 = `${
|
|
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
|
|
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
|
|
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
|
}
|
|
@@ -5218,7 +5371,7 @@ var vitestCoverageRule = {
|
|
|
5218
5371
|
message: 'package.json must declare a "test:unit:coverage" script that runs Vitest with coverage.'
|
|
5219
5372
|
});
|
|
5220
5373
|
}
|
|
5221
|
-
const configName = VITEST_CONFIG_NAMES.find((name) => existsSync5(
|
|
5374
|
+
const configName = VITEST_CONFIG_NAMES.find((name) => existsSync5(path41.join(context.cwd, name)));
|
|
5222
5375
|
if (!configName) {
|
|
5223
5376
|
context.report({
|
|
5224
5377
|
node,
|
|
@@ -5226,7 +5379,7 @@ var vitestCoverageRule = {
|
|
|
5226
5379
|
});
|
|
5227
5380
|
return;
|
|
5228
5381
|
}
|
|
5229
|
-
const content = readFileSync8(
|
|
5382
|
+
const content = readFileSync8(path41.join(context.cwd, configName), "utf8");
|
|
5230
5383
|
for (const metric of THRESHOLD_METRICS) {
|
|
5231
5384
|
if (!new RegExp(`\\b${metric}\\s*:\\s*[1-9]\\d*`).test(content)) {
|
|
5232
5385
|
context.report({ node, message: `${configName} must set a coverage threshold above zero for ${metric}.` });
|
|
@@ -5272,7 +5425,7 @@ var nextjsPackageJsonRules = {
|
|
|
5272
5425
|
};
|
|
5273
5426
|
|
|
5274
5427
|
// eslint/rules/prefer-enum.ts
|
|
5275
|
-
import
|
|
5428
|
+
import path42 from "path";
|
|
5276
5429
|
function isConstAssertion(node) {
|
|
5277
5430
|
const typeAnnotation = node.typeAnnotation;
|
|
5278
5431
|
return typeAnnotation?.type === "TSTypeReference" && typeAnnotation.typeName?.type === "Identifier" && typeAnnotation.typeName.name === "const";
|
|
@@ -5324,9 +5477,9 @@ var preferEnumRule = {
|
|
|
5324
5477
|
}
|
|
5325
5478
|
},
|
|
5326
5479
|
create(context) {
|
|
5327
|
-
const filename =
|
|
5480
|
+
const filename = path42.resolve(context.filename);
|
|
5328
5481
|
const sourceRoot = sourceRootOf(context);
|
|
5329
|
-
if (!filename.startsWith(sourceRoot +
|
|
5482
|
+
if (!filename.startsWith(sourceRoot + path42.sep)) return {};
|
|
5330
5483
|
const objectSchemas = /* @__PURE__ */ new Map();
|
|
5331
5484
|
const discriminatedUnions = [];
|
|
5332
5485
|
const reportedDiscriminants = /* @__PURE__ */ new Set();
|
|
@@ -5397,7 +5550,7 @@ var preferEnumRule = {
|
|
|
5397
5550
|
};
|
|
5398
5551
|
|
|
5399
5552
|
// eslint/rules/pure-function-extract.ts
|
|
5400
|
-
import
|
|
5553
|
+
import path43 from "path";
|
|
5401
5554
|
var ROUTE_HANDLER_EXPORT_NAMES = /* @__PURE__ */ new Set([
|
|
5402
5555
|
"GET",
|
|
5403
5556
|
"POST",
|
|
@@ -5462,12 +5615,12 @@ var pureFunctionExtractRule = {
|
|
|
5462
5615
|
},
|
|
5463
5616
|
create(context) {
|
|
5464
5617
|
const filename = context.filename;
|
|
5465
|
-
const isRouteFile =
|
|
5618
|
+
const isRouteFile = path43.basename(filename) === "route.ts";
|
|
5466
5619
|
const isComponentFile = filename.endsWith(".tsx") || filename.endsWith(".jsx");
|
|
5467
5620
|
const sourceRoot = sourceRootOf(context);
|
|
5468
|
-
const relative =
|
|
5621
|
+
const relative = path43.relative(sourceRoot, filename);
|
|
5469
5622
|
if (relative.startsWith("..")) return {};
|
|
5470
|
-
const segments = relative.split(
|
|
5623
|
+
const segments = relative.split(path43.sep);
|
|
5471
5624
|
const folders = segments.slice(0, -1);
|
|
5472
5625
|
const isHookSupportFile = folders.includes("hooks") && /\.(?:[cm]?[jt]s)$/.test(filename);
|
|
5473
5626
|
if (!isComponentFile && !isRouteFile && !isHookSupportFile) return {};
|
|
@@ -5708,7 +5861,7 @@ var repeatedStructureRule = {
|
|
|
5708
5861
|
|
|
5709
5862
|
// eslint/rules/require-barrel-star-exports.ts
|
|
5710
5863
|
import fs5 from "fs";
|
|
5711
|
-
import
|
|
5864
|
+
import path44 from "path";
|
|
5712
5865
|
var SUPPORT_FOLDERS3 = /* @__PURE__ */ new Set(["constants", "types", "schemas"]);
|
|
5713
5866
|
var INDEX_NAMES = /* @__PURE__ */ new Set(["index.ts", "index.tsx", "index.mts", "index.cts"]);
|
|
5714
5867
|
var MODULE_EXTENSIONS3 = [".ts", ".tsx", ".mts", ".cts", ".js", ".jsx", ".mjs", ".cjs"];
|
|
@@ -5716,9 +5869,9 @@ function resolveSiblingModule(indexFile, specifier) {
|
|
|
5716
5869
|
if (!specifier.startsWith("./")) return void 0;
|
|
5717
5870
|
const relative = specifier.slice(2);
|
|
5718
5871
|
if (!relative || relative.includes("/")) return void 0;
|
|
5719
|
-
const directory =
|
|
5720
|
-
const direct =
|
|
5721
|
-
const candidates =
|
|
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}`);
|
|
5722
5875
|
return candidates.find((candidate) => fs5.existsSync(candidate) && fs5.statSync(candidate).isFile());
|
|
5723
5876
|
}
|
|
5724
5877
|
var requireBarrelStarExportsRule = {
|
|
@@ -5731,9 +5884,9 @@ var requireBarrelStarExportsRule = {
|
|
|
5731
5884
|
fixable: "code"
|
|
5732
5885
|
},
|
|
5733
5886
|
create(context) {
|
|
5734
|
-
const filename =
|
|
5735
|
-
if (!INDEX_NAMES.has(
|
|
5736
|
-
if (!SUPPORT_FOLDERS3.has(
|
|
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 {};
|
|
5737
5890
|
return {
|
|
5738
5891
|
ExportNamedDeclaration(node) {
|
|
5739
5892
|
const sourceNode = node.source;
|
|
@@ -5786,7 +5939,7 @@ var requireBarrelStarExportsRule = {
|
|
|
5786
5939
|
};
|
|
5787
5940
|
|
|
5788
5941
|
// eslint/rules/root-support-placement.ts
|
|
5789
|
-
import
|
|
5942
|
+
import path45 from "path";
|
|
5790
5943
|
function isSupportFolder(value) {
|
|
5791
5944
|
return value === "utils" || value === "types" || value === "schemas" || value === "constants";
|
|
5792
5945
|
}
|
|
@@ -5819,7 +5972,7 @@ var rootSupportPlacementRule = {
|
|
|
5819
5972
|
},
|
|
5820
5973
|
create(context) {
|
|
5821
5974
|
const sourceRoot = sourceRootOf(context);
|
|
5822
|
-
const file =
|
|
5975
|
+
const file = path45.resolve(context.filename);
|
|
5823
5976
|
const segments = segmentsOf(file, sourceRoot);
|
|
5824
5977
|
const folderSegments = folderSegmentsOf(file, sourceRoot);
|
|
5825
5978
|
const supportFolder = folderSegments[folderSegments.length - 1];
|
|
@@ -5859,7 +6012,7 @@ var rootSupportPlacementRule = {
|
|
|
5859
6012
|
};
|
|
5860
6013
|
|
|
5861
6014
|
// eslint/rules/route-handler-shape.ts
|
|
5862
|
-
import
|
|
6015
|
+
import path46 from "path";
|
|
5863
6016
|
import ts7 from "typescript";
|
|
5864
6017
|
var HTTP_METHODS2 = /* @__PURE__ */ new Set(["GET", "POST", "PUT", "PATCH", "DELETE", "HEAD", "OPTIONS"]);
|
|
5865
6018
|
var REQUIRED_BOUNDARY = "withResponse";
|
|
@@ -5944,7 +6097,7 @@ var routeHandlerShapeRule = {
|
|
|
5944
6097
|
}
|
|
5945
6098
|
},
|
|
5946
6099
|
create(context) {
|
|
5947
|
-
if (
|
|
6100
|
+
if (path46.basename(context.filename) !== "route.ts") return {};
|
|
5948
6101
|
const sourceText = context.sourceCode.text;
|
|
5949
6102
|
function reportUnwrapped(node, name) {
|
|
5950
6103
|
context.report({
|
|
@@ -6003,7 +6156,7 @@ var routeHandlerShapeRule = {
|
|
|
6003
6156
|
};
|
|
6004
6157
|
|
|
6005
6158
|
// eslint/rules/schema-casing.ts
|
|
6006
|
-
import
|
|
6159
|
+
import path47 from "path";
|
|
6007
6160
|
function isCamelCase(name) {
|
|
6008
6161
|
return /^[a-z][a-zA-Z0-9]*$/.test(name);
|
|
6009
6162
|
}
|
|
@@ -6031,9 +6184,9 @@ var schemaCasingRule = {
|
|
|
6031
6184
|
}
|
|
6032
6185
|
},
|
|
6033
6186
|
create(context) {
|
|
6034
|
-
const filename =
|
|
6187
|
+
const filename = path47.resolve(context.filename);
|
|
6035
6188
|
const sourceRoot = sourceRootOf(context);
|
|
6036
|
-
if (!filename.startsWith(sourceRoot +
|
|
6189
|
+
if (!filename.startsWith(sourceRoot + path47.sep)) return {};
|
|
6037
6190
|
let zodLocalName;
|
|
6038
6191
|
return {
|
|
6039
6192
|
ImportDeclaration(node) {
|
|
@@ -6065,7 +6218,7 @@ var schemaCasingRule = {
|
|
|
6065
6218
|
};
|
|
6066
6219
|
|
|
6067
6220
|
// eslint/rules/sole-state-owner.ts
|
|
6068
|
-
import
|
|
6221
|
+
import path48 from "path";
|
|
6069
6222
|
import ts8 from "typescript";
|
|
6070
6223
|
function findStateHooks(node) {
|
|
6071
6224
|
const hooks = [];
|
|
@@ -6145,7 +6298,7 @@ var soleStateOwnerRule = {
|
|
|
6145
6298
|
}
|
|
6146
6299
|
},
|
|
6147
6300
|
create(context) {
|
|
6148
|
-
const filename =
|
|
6301
|
+
const filename = path48.resolve(context.filename);
|
|
6149
6302
|
if (!filename.endsWith(".tsx") && !filename.endsWith(".jsx")) return {};
|
|
6150
6303
|
const text = context.sourceCode.text;
|
|
6151
6304
|
const components = parseComponentInfo(text, filename);
|
|
@@ -6224,7 +6377,7 @@ function usesOutsideJsx(declaration, hook, children) {
|
|
|
6224
6377
|
}
|
|
6225
6378
|
|
|
6226
6379
|
// eslint/rules/source-under-src.ts
|
|
6227
|
-
import
|
|
6380
|
+
import path49 from "path";
|
|
6228
6381
|
var NON_SOURCE_ROOT_DIRS = /* @__PURE__ */ new Set([
|
|
6229
6382
|
".agents",
|
|
6230
6383
|
".cache",
|
|
@@ -6265,14 +6418,14 @@ var sourceUnderSrcRule = {
|
|
|
6265
6418
|
}
|
|
6266
6419
|
},
|
|
6267
6420
|
create(context) {
|
|
6268
|
-
const filename =
|
|
6421
|
+
const filename = path49.resolve(context.filename);
|
|
6269
6422
|
if (!MODULE_EXTENSION.test(filename)) return {};
|
|
6270
|
-
const relative =
|
|
6423
|
+
const relative = path49.relative(context.cwd, filename).replace(/\\/g, "/");
|
|
6271
6424
|
if (relative === "src" || relative.startsWith("src/")) return {};
|
|
6272
6425
|
const topLevel = relative.split("/")[0] ?? "";
|
|
6273
6426
|
if (NON_SOURCE_ROOT_DIRS.has(topLevel)) return {};
|
|
6274
6427
|
if (!relative.includes("/")) {
|
|
6275
|
-
const basename =
|
|
6428
|
+
const basename = path49.basename(filename);
|
|
6276
6429
|
if (CONFIG_FILE.test(basename) || DECLARATION_FILE.test(basename) || basename.startsWith(".")) return {};
|
|
6277
6430
|
}
|
|
6278
6431
|
return {
|
|
@@ -6288,7 +6441,7 @@ var sourceUnderSrcRule = {
|
|
|
6288
6441
|
};
|
|
6289
6442
|
|
|
6290
6443
|
// eslint/rules/stay-flat.ts
|
|
6291
|
-
import
|
|
6444
|
+
import path50 from "path";
|
|
6292
6445
|
var stayFlatRule = {
|
|
6293
6446
|
meta: {
|
|
6294
6447
|
schema: [],
|
|
@@ -6299,7 +6452,7 @@ var stayFlatRule = {
|
|
|
6299
6452
|
},
|
|
6300
6453
|
create(context) {
|
|
6301
6454
|
const sourceRoot = sourceRootOf(context);
|
|
6302
|
-
const file =
|
|
6455
|
+
const file = path50.resolve(context.filename);
|
|
6303
6456
|
const segments = segmentsOf(file, sourceRoot);
|
|
6304
6457
|
if (segments.length !== 3 || segments[0] !== "features") return {};
|
|
6305
6458
|
const index = getProjectIndex(sourceRoot);
|
|
@@ -6339,7 +6492,7 @@ var stayFlatRule = {
|
|
|
6339
6492
|
};
|
|
6340
6493
|
|
|
6341
6494
|
// eslint/rules/support-file-placement.ts
|
|
6342
|
-
import
|
|
6495
|
+
import path51 from "path";
|
|
6343
6496
|
var CONFIG_OWNED_FOLDERS = /* @__PURE__ */ new Set(["types", "constants"]);
|
|
6344
6497
|
var EXPORT_KIND_BY_SUPPORT_FOLDER = /* @__PURE__ */ new Map([
|
|
6345
6498
|
["constants", "constant"],
|
|
@@ -6364,7 +6517,7 @@ var supportFilePlacementRule = {
|
|
|
6364
6517
|
},
|
|
6365
6518
|
create(context) {
|
|
6366
6519
|
const sourceRoot = sourceRootOf(context);
|
|
6367
|
-
const supportFile =
|
|
6520
|
+
const supportFile = path51.resolve(context.filename);
|
|
6368
6521
|
const currentFolder = folderSegmentsOf(supportFile, sourceRoot);
|
|
6369
6522
|
const supportFolder = currentFolder[currentFolder.length - 1];
|
|
6370
6523
|
if (supportFolder === void 0 || !SUPPORT_FOLDERS.has(supportFolder)) return {};
|
|
@@ -6418,7 +6571,7 @@ var supportFilePlacementRule = {
|
|
|
6418
6571
|
|
|
6419
6572
|
// eslint/rules/support-folder-shape.ts
|
|
6420
6573
|
import fs6 from "fs";
|
|
6421
|
-
import
|
|
6574
|
+
import path52 from "path";
|
|
6422
6575
|
var SUPPORT_FOLDERS4 = /* @__PURE__ */ new Set(["constants", "types", "schemas"]);
|
|
6423
6576
|
var INDEX_NAMES2 = /* @__PURE__ */ new Set(["index.ts", "index.tsx", "index.mts", "index.cts"]);
|
|
6424
6577
|
var supportFolderShapeRule = {
|
|
@@ -6430,12 +6583,12 @@ var supportFolderShapeRule = {
|
|
|
6430
6583
|
}
|
|
6431
6584
|
},
|
|
6432
6585
|
create(context) {
|
|
6433
|
-
const filename =
|
|
6434
|
-
const baseName =
|
|
6586
|
+
const filename = path52.resolve(context.filename);
|
|
6587
|
+
const baseName = path52.basename(filename);
|
|
6435
6588
|
if (!INDEX_NAMES2.has(baseName)) return {};
|
|
6436
|
-
const folder =
|
|
6589
|
+
const folder = path52.basename(path52.dirname(filename));
|
|
6437
6590
|
if (!SUPPORT_FOLDERS4.has(folder)) return {};
|
|
6438
|
-
const directory =
|
|
6591
|
+
const directory = path52.dirname(filename);
|
|
6439
6592
|
let entries;
|
|
6440
6593
|
try {
|
|
6441
6594
|
entries = fs6.readdirSync(directory);
|
|
@@ -6453,7 +6606,7 @@ var supportFolderShapeRule = {
|
|
|
6453
6606
|
for (const match of source.matchAll(exportPattern)) {
|
|
6454
6607
|
hasAnyReExport = true;
|
|
6455
6608
|
const specifier = match.groups?.specifier;
|
|
6456
|
-
if (specifier?.startsWith(".")) exportedFiles.add(
|
|
6609
|
+
if (specifier?.startsWith(".")) exportedFiles.add(path52.basename(specifier));
|
|
6457
6610
|
}
|
|
6458
6611
|
const guide = `docs/next-codebase-guide/rules/${folder === "constants" ? "constants" : "types-and-schemas"}-rule.md`;
|
|
6459
6612
|
if (siblingModules.length === 0) {
|
|
@@ -6632,11 +6785,11 @@ var baseLayerPairRule = {
|
|
|
6632
6785
|
|
|
6633
6786
|
// eslint/rules/tailwind/css-entry-point.ts
|
|
6634
6787
|
import { statSync as statSync4 } from "fs";
|
|
6635
|
-
import
|
|
6788
|
+
import path55 from "path";
|
|
6636
6789
|
|
|
6637
6790
|
// eslint/rules/tailwind/source-files.ts
|
|
6638
6791
|
import { readdirSync as readdirSync3, readFileSync as readFileSync9, statSync as statSync3 } from "fs";
|
|
6639
|
-
import
|
|
6792
|
+
import path53 from "path";
|
|
6640
6793
|
var CSS_EXTENSIONS = [".css"];
|
|
6641
6794
|
var MODULE_EXTENSIONS4 = [".ts", ".tsx", ".mts", ".cts", ".js", ".jsx", ".mjs", ".cjs"];
|
|
6642
6795
|
var SOURCE_EXTENSIONS = [...MODULE_EXTENSIONS4, ...CSS_EXTENSIONS];
|
|
@@ -6649,7 +6802,7 @@ function findFiles(dir, extensions) {
|
|
|
6649
6802
|
}
|
|
6650
6803
|
return entries.flatMap((entry) => {
|
|
6651
6804
|
if (entry.startsWith(".") || entry === "node_modules") return [];
|
|
6652
|
-
const entryPath =
|
|
6805
|
+
const entryPath = path53.join(dir, entry);
|
|
6653
6806
|
let stats;
|
|
6654
6807
|
try {
|
|
6655
6808
|
stats = statSync3(entryPath);
|
|
@@ -6657,7 +6810,7 @@ function findFiles(dir, extensions) {
|
|
|
6657
6810
|
return [];
|
|
6658
6811
|
}
|
|
6659
6812
|
if (stats.isDirectory()) return findFiles(entryPath, extensions);
|
|
6660
|
-
return extensions.includes(
|
|
6813
|
+
return extensions.includes(path53.extname(entry)) ? [entryPath] : [];
|
|
6661
6814
|
});
|
|
6662
6815
|
}
|
|
6663
6816
|
function cachedTextReader() {
|
|
@@ -6680,7 +6833,7 @@ function escapeRegExp(text) {
|
|
|
6680
6833
|
}
|
|
6681
6834
|
|
|
6682
6835
|
// eslint/rules/tailwind/stylesheet-graph.ts
|
|
6683
|
-
import
|
|
6836
|
+
import path54 from "path";
|
|
6684
6837
|
function registersTailwind(text) {
|
|
6685
6838
|
return /@import\s+(?:url\(\s*)?["']tailwindcss["']\s*\)?/i.test(text);
|
|
6686
6839
|
}
|
|
@@ -6694,25 +6847,25 @@ function moduleImports(text, fileName) {
|
|
|
6694
6847
|
return new RegExp(`(?:import|require)\\s*\\(?\\s*["'][^"']*${escaped}["']`, "i").test(text);
|
|
6695
6848
|
}
|
|
6696
6849
|
function resolveSpecifier2(fromFile, spec, sourceRoot) {
|
|
6697
|
-
if (spec.startsWith("/")) return
|
|
6698
|
-
if (spec.startsWith("./") || spec.startsWith("../")) return
|
|
6699
|
-
if (spec.startsWith("@/")) return
|
|
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));
|
|
6700
6853
|
return void 0;
|
|
6701
6854
|
}
|
|
6702
6855
|
function buildStylesheetGraph(options) {
|
|
6703
6856
|
const { cssFiles, sourceRoot, textOf } = options;
|
|
6704
|
-
const cssSet = new Set(cssFiles.map((file) =>
|
|
6857
|
+
const cssSet = new Set(cssFiles.map((file) => path54.normalize(file)));
|
|
6705
6858
|
const globals = cssFiles.filter((file) => registersTailwind(textOf(file)));
|
|
6706
6859
|
const reachable = /* @__PURE__ */ new Set();
|
|
6707
6860
|
const queue = [...globals];
|
|
6708
|
-
for (const global of globals) reachable.add(
|
|
6861
|
+
for (const global of globals) reachable.add(path54.normalize(global));
|
|
6709
6862
|
while (queue.length > 0) {
|
|
6710
6863
|
const from = queue.shift();
|
|
6711
6864
|
if (!from) continue;
|
|
6712
6865
|
for (const spec of importedSpecifiers(textOf(from))) {
|
|
6713
6866
|
const target = resolveSpecifier2(from, spec, sourceRoot);
|
|
6714
6867
|
if (!target) continue;
|
|
6715
|
-
const normalized =
|
|
6868
|
+
const normalized = path54.normalize(target);
|
|
6716
6869
|
if (cssSet.has(normalized) && !reachable.has(normalized)) {
|
|
6717
6870
|
reachable.add(normalized);
|
|
6718
6871
|
queue.push(normalized);
|
|
@@ -6724,7 +6877,7 @@ function buildStylesheetGraph(options) {
|
|
|
6724
6877
|
for (const spec of importedSpecifiers(textOf(global))) {
|
|
6725
6878
|
const target = resolveSpecifier2(global, spec, sourceRoot);
|
|
6726
6879
|
if (!target) continue;
|
|
6727
|
-
const normalized =
|
|
6880
|
+
const normalized = path54.normalize(target);
|
|
6728
6881
|
if (cssSet.has(normalized)) directChildren.add(normalized);
|
|
6729
6882
|
}
|
|
6730
6883
|
}
|
|
@@ -6732,8 +6885,8 @@ function buildStylesheetGraph(options) {
|
|
|
6732
6885
|
}
|
|
6733
6886
|
|
|
6734
6887
|
// eslint/rules/tailwind/css-entry-point.ts
|
|
6735
|
-
var APP_STYLES_DIR =
|
|
6736
|
-
var GLOBAL_STYLESHEET_PATH =
|
|
6888
|
+
var APP_STYLES_DIR = path55.join("app", "styles");
|
|
6889
|
+
var GLOBAL_STYLESHEET_PATH = path55.join(APP_STYLES_DIR, "globals.css");
|
|
6737
6890
|
var cssEntryPointRule = {
|
|
6738
6891
|
meta: {
|
|
6739
6892
|
schema: [],
|
|
@@ -6759,8 +6912,8 @@ var cssEntryPointRule = {
|
|
|
6759
6912
|
return {
|
|
6760
6913
|
"StyleSheet:exit"(node) {
|
|
6761
6914
|
if (globals.length === 0) return;
|
|
6762
|
-
const current =
|
|
6763
|
-
const relative =
|
|
6915
|
+
const current = path55.normalize(path55.resolve(context.filename));
|
|
6916
|
+
const relative = path55.relative(sourceRoot, current);
|
|
6764
6917
|
if (globals.includes(current)) {
|
|
6765
6918
|
if (globals.length > 1) {
|
|
6766
6919
|
context.report({
|
|
@@ -6776,7 +6929,7 @@ var cssEntryPointRule = {
|
|
|
6776
6929
|
});
|
|
6777
6930
|
return;
|
|
6778
6931
|
}
|
|
6779
|
-
const basename =
|
|
6932
|
+
const basename = path55.basename(current);
|
|
6780
6933
|
const importCount = moduleFiles.filter((modulePath) => moduleImports(textOf(modulePath), basename)).length;
|
|
6781
6934
|
if (importCount !== 1) {
|
|
6782
6935
|
context.report({
|
|
@@ -6786,7 +6939,7 @@ var cssEntryPointRule = {
|
|
|
6786
6939
|
}
|
|
6787
6940
|
return;
|
|
6788
6941
|
}
|
|
6789
|
-
const isInAppStyles = relative === APP_STYLES_DIR || relative.startsWith(`${APP_STYLES_DIR}${
|
|
6942
|
+
const isInAppStyles = relative === APP_STYLES_DIR || relative.startsWith(`${APP_STYLES_DIR}${path55.sep}`);
|
|
6790
6943
|
if (!isInAppStyles) {
|
|
6791
6944
|
context.report({
|
|
6792
6945
|
node,
|
|
@@ -7275,7 +7428,7 @@ var tailwindRules = {
|
|
|
7275
7428
|
};
|
|
7276
7429
|
|
|
7277
7430
|
// eslint/rules/type-extraction.ts
|
|
7278
|
-
import
|
|
7431
|
+
import path56 from "path";
|
|
7279
7432
|
var typeExtractionRule = {
|
|
7280
7433
|
meta: {
|
|
7281
7434
|
schema: [],
|
|
@@ -7286,7 +7439,7 @@ var typeExtractionRule = {
|
|
|
7286
7439
|
},
|
|
7287
7440
|
create(context) {
|
|
7288
7441
|
const sourceRoot = sourceRootOf(context);
|
|
7289
|
-
const file =
|
|
7442
|
+
const file = path56.resolve(context.filename);
|
|
7290
7443
|
const segments = segmentsOf(file, sourceRoot);
|
|
7291
7444
|
if (segments.length === 0) return {};
|
|
7292
7445
|
const index = getProjectIndex(sourceRoot);
|
|
@@ -7421,7 +7574,7 @@ var uiStateRule = {
|
|
|
7421
7574
|
// eslint/rules/unknown-utility.ts
|
|
7422
7575
|
import { existsSync as existsSync6, readdirSync as readdirSync4, readFileSync as readFileSync10, statSync as statSync6 } from "fs";
|
|
7423
7576
|
import { createRequire } from "module";
|
|
7424
|
-
import
|
|
7577
|
+
import path57 from "path";
|
|
7425
7578
|
var PREFIX_NAMESPACES = {
|
|
7426
7579
|
bg: ["color"],
|
|
7427
7580
|
text: ["color", "text"],
|
|
@@ -7661,7 +7814,7 @@ function stylesheetFiles(dir) {
|
|
|
7661
7814
|
}
|
|
7662
7815
|
return entries.flatMap((entry) => {
|
|
7663
7816
|
if (entry.startsWith(".") || entry === "node_modules") return [];
|
|
7664
|
-
const entryPath =
|
|
7817
|
+
const entryPath = path57.join(dir, entry);
|
|
7665
7818
|
let stats;
|
|
7666
7819
|
try {
|
|
7667
7820
|
stats = statSync6(entryPath);
|
|
@@ -7669,7 +7822,7 @@ function stylesheetFiles(dir) {
|
|
|
7669
7822
|
return [];
|
|
7670
7823
|
}
|
|
7671
7824
|
if (stats.isDirectory()) return stylesheetFiles(entryPath);
|
|
7672
|
-
return
|
|
7825
|
+
return path57.extname(entry) === ".css" ? [entryPath] : [];
|
|
7673
7826
|
});
|
|
7674
7827
|
}
|
|
7675
7828
|
function packageNameOf(specifier) {
|
|
@@ -7680,10 +7833,10 @@ function packageNameOf(specifier) {
|
|
|
7680
7833
|
function resolvePackageStylesheet(fromFile, specifier) {
|
|
7681
7834
|
const packageName = packageNameOf(specifier);
|
|
7682
7835
|
if (!packageName || packageName === "tailwindcss") return void 0;
|
|
7683
|
-
let directory =
|
|
7684
|
-
while (directory !==
|
|
7685
|
-
const packageRoot =
|
|
7686
|
-
const manifestPath =
|
|
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");
|
|
7687
7840
|
if (existsSync6(manifestPath)) {
|
|
7688
7841
|
try {
|
|
7689
7842
|
const manifest = readFileSync10(manifestPath, "utf8");
|
|
@@ -7691,13 +7844,13 @@ function resolvePackageStylesheet(fromFile, specifier) {
|
|
|
7691
7844
|
const main = /"main"\s*:\s*"(?<file>[^"]+\.css)"/.exec(manifest)?.groups?.file;
|
|
7692
7845
|
const target = stylesheet ?? main;
|
|
7693
7846
|
if (!target) return void 0;
|
|
7694
|
-
const resolved =
|
|
7847
|
+
const resolved = path57.resolve(packageRoot, target);
|
|
7695
7848
|
return existsSync6(resolved) ? resolved : void 0;
|
|
7696
7849
|
} catch {
|
|
7697
7850
|
return void 0;
|
|
7698
7851
|
}
|
|
7699
7852
|
}
|
|
7700
|
-
directory =
|
|
7853
|
+
directory = path57.dirname(directory);
|
|
7701
7854
|
}
|
|
7702
7855
|
return void 0;
|
|
7703
7856
|
}
|
|
@@ -7948,7 +8101,7 @@ var unknownUtilityRule = {
|
|
|
7948
8101
|
};
|
|
7949
8102
|
|
|
7950
8103
|
// eslint/rules/util-file-name.ts
|
|
7951
|
-
import
|
|
8104
|
+
import path58 from "path";
|
|
7952
8105
|
function toKebabCase2(value) {
|
|
7953
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();
|
|
7954
8107
|
}
|
|
@@ -7961,7 +8114,7 @@ var utilFileNameRule = {
|
|
|
7961
8114
|
}
|
|
7962
8115
|
},
|
|
7963
8116
|
create(context) {
|
|
7964
|
-
const filename =
|
|
8117
|
+
const filename = path58.resolve(context.filename);
|
|
7965
8118
|
const segments = filename.replace(/\\/g, "/").split("/");
|
|
7966
8119
|
if (!segments.includes("utils")) return {};
|
|
7967
8120
|
let module;
|
|
@@ -7975,13 +8128,13 @@ var utilFileNameRule = {
|
|
|
7975
8128
|
const functionName = functions[0]?.name;
|
|
7976
8129
|
if (!functionName) return {};
|
|
7977
8130
|
const expected = toKebabCase2(functionName);
|
|
7978
|
-
const actual =
|
|
8131
|
+
const actual = path58.basename(filename, path58.extname(filename));
|
|
7979
8132
|
if (!expected || actual === expected) return {};
|
|
7980
8133
|
return {
|
|
7981
8134
|
Program(node) {
|
|
7982
8135
|
context.report({
|
|
7983
8136
|
node,
|
|
7984
|
-
message: `A utility file exporting ${functionName} must be named ${expected}.${
|
|
8137
|
+
message: `A utility file exporting ${functionName} must be named ${expected}.${path58.extname(filename).slice(1)}.`
|
|
7985
8138
|
});
|
|
7986
8139
|
}
|
|
7987
8140
|
};
|
|
@@ -7989,7 +8142,7 @@ var utilFileNameRule = {
|
|
|
7989
8142
|
};
|
|
7990
8143
|
|
|
7991
8144
|
// eslint/rules/value-extraction.ts
|
|
7992
|
-
import
|
|
8145
|
+
import path59 from "path";
|
|
7993
8146
|
var valueExtractionRule = {
|
|
7994
8147
|
meta: {
|
|
7995
8148
|
schema: [],
|
|
@@ -8000,7 +8153,7 @@ var valueExtractionRule = {
|
|
|
8000
8153
|
},
|
|
8001
8154
|
create(context) {
|
|
8002
8155
|
const sourceRoot = sourceRootOf(context);
|
|
8003
|
-
const file =
|
|
8156
|
+
const file = path59.resolve(context.filename);
|
|
8004
8157
|
const segments = segmentsOf(file, sourceRoot);
|
|
8005
8158
|
if (segments.length === 0 || segments[0] !== "app") return {};
|
|
8006
8159
|
const index = getProjectIndex(sourceRoot);
|
|
@@ -8022,7 +8175,7 @@ var valueExtractionRule = {
|
|
|
8022
8175
|
|
|
8023
8176
|
// eslint/rules/vulyk/tracked-docs.ts
|
|
8024
8177
|
import { existsSync as existsSync7, readFileSync as readFileSync11 } from "fs";
|
|
8025
|
-
import
|
|
8178
|
+
import path60 from "path";
|
|
8026
8179
|
var PASIKA_REPO = "Bredansky/pasika";
|
|
8027
8180
|
var BASE_REQUIRED_TRACKED_DOCS = [
|
|
8028
8181
|
{ name: "documentation-guide", path: "docs/documentation-guide" },
|
|
@@ -8055,8 +8208,8 @@ var trackedDocsRule = {
|
|
|
8055
8208
|
if (!context.filename.endsWith("package.json")) return;
|
|
8056
8209
|
const root = node.body;
|
|
8057
8210
|
if (root.type !== "Object") return;
|
|
8058
|
-
const projectRoot =
|
|
8059
|
-
const configPath =
|
|
8211
|
+
const projectRoot = path60.dirname(path60.resolve(context.filename));
|
|
8212
|
+
const configPath = path60.join(projectRoot, "vulyk.config.ts");
|
|
8060
8213
|
if (!existsSync7(configPath)) {
|
|
8061
8214
|
context.report({
|
|
8062
8215
|
node,
|
|
@@ -8081,7 +8234,7 @@ var trackedDocsRule = {
|
|
|
8081
8234
|
});
|
|
8082
8235
|
}
|
|
8083
8236
|
}
|
|
8084
|
-
const agentsPath =
|
|
8237
|
+
const agentsPath = path60.join(projectRoot, "AGENTS.md");
|
|
8085
8238
|
if (!existsSync7(agentsPath)) {
|
|
8086
8239
|
context.report({
|
|
8087
8240
|
node,
|
|
@@ -8140,12 +8293,12 @@ var vulykRules = {
|
|
|
8140
8293
|
};
|
|
8141
8294
|
|
|
8142
8295
|
// eslint/rules/with-response-helper.ts
|
|
8143
|
-
var
|
|
8144
|
-
var
|
|
8145
|
-
var
|
|
8146
|
-
var
|
|
8147
|
-
var
|
|
8148
|
-
function
|
|
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) {
|
|
8149
8302
|
return node?.type === "Identifier" && node.name === name;
|
|
8150
8303
|
}
|
|
8151
8304
|
var withResponseHelperRule = {
|
|
@@ -8153,24 +8306,24 @@ var withResponseHelperRule = {
|
|
|
8153
8306
|
schema: [],
|
|
8154
8307
|
type: "problem",
|
|
8155
8308
|
docs: {
|
|
8156
|
-
description: `Require ${
|
|
8309
|
+
description: `Require ${HELPER3} to be imported from ${ENTRY3} rather than declared in the repository.`
|
|
8157
8310
|
}
|
|
8158
8311
|
},
|
|
8159
8312
|
create(context) {
|
|
8160
8313
|
const checkSource = (node) => {
|
|
8161
|
-
if (!node.source || node.source.value ===
|
|
8314
|
+
if (!node.source || node.source.value === ENTRY3) return;
|
|
8162
8315
|
for (const specifier of node.specifiers) {
|
|
8163
|
-
if (!
|
|
8164
|
-
context.report({ node: specifier, message:
|
|
8316
|
+
if (!isNamed3(specifier.local, HELPER3)) continue;
|
|
8317
|
+
context.report({ node: specifier, message: IMPORTED3 });
|
|
8165
8318
|
}
|
|
8166
8319
|
};
|
|
8167
8320
|
return {
|
|
8168
8321
|
FunctionDeclaration(node) {
|
|
8169
|
-
if (
|
|
8322
|
+
if (isNamed3(node.id, HELPER3)) context.report({ node, message: DECLARED3 });
|
|
8170
8323
|
},
|
|
8171
8324
|
VariableDeclarator(node) {
|
|
8172
|
-
if (
|
|
8173
|
-
context.report({ node, message:
|
|
8325
|
+
if (isNamed3(node.id.type === "Identifier" ? node.id : null, HELPER3)) {
|
|
8326
|
+
context.report({ node, message: DECLARED3 });
|
|
8174
8327
|
}
|
|
8175
8328
|
},
|
|
8176
8329
|
ImportDeclaration: checkSource,
|
|
@@ -8181,7 +8334,7 @@ var withResponseHelperRule = {
|
|
|
8181
8334
|
|
|
8182
8335
|
// eslint/rules/zirka-baseline.ts
|
|
8183
8336
|
import fs7 from "fs";
|
|
8184
|
-
import
|
|
8337
|
+
import path61 from "path";
|
|
8185
8338
|
var ESLINT_CONFIG = /^eslint\.config\.(?:ts|mts|cts|js|mjs|cjs)$/;
|
|
8186
8339
|
var PRETTIER_CONFIGS = [
|
|
8187
8340
|
"prettier.config.mjs",
|
|
@@ -8200,10 +8353,10 @@ var zirkaBaselineRule = {
|
|
|
8200
8353
|
}
|
|
8201
8354
|
},
|
|
8202
8355
|
create(context) {
|
|
8203
|
-
const filename =
|
|
8204
|
-
const basename =
|
|
8356
|
+
const filename = path61.resolve(context.filename);
|
|
8357
|
+
const basename = path61.basename(filename);
|
|
8205
8358
|
if (!ESLINT_CONFIG.test(basename)) return {};
|
|
8206
|
-
const projectRoot =
|
|
8359
|
+
const projectRoot = path61.dirname(filename);
|
|
8207
8360
|
const report3 = (message) => {
|
|
8208
8361
|
context.report({
|
|
8209
8362
|
node: context.sourceCode.ast,
|
|
@@ -8218,7 +8371,7 @@ var zirkaBaselineRule = {
|
|
|
8218
8371
|
'ESLint config must take its configuration from zirka (import { styleguide } from "zirka") instead of restating rules locally.'
|
|
8219
8372
|
);
|
|
8220
8373
|
}
|
|
8221
|
-
const tsconfigPath =
|
|
8374
|
+
const tsconfigPath = path61.join(projectRoot, "tsconfig.json");
|
|
8222
8375
|
if (!fs7.existsSync(tsconfigPath)) {
|
|
8223
8376
|
report3('No tsconfig.json found. Create one extending the zirka TypeScript base config ("zirka/typescript").');
|
|
8224
8377
|
} else {
|
|
@@ -8236,13 +8389,13 @@ var zirkaBaselineRule = {
|
|
|
8236
8389
|
report3('tsconfig.json must extend the zirka TypeScript base config ("zirka/typescript").');
|
|
8237
8390
|
}
|
|
8238
8391
|
}
|
|
8239
|
-
const prettierConfigFile = PRETTIER_CONFIGS.find((name) => fs7.existsSync(
|
|
8392
|
+
const prettierConfigFile = PRETTIER_CONFIGS.find((name) => fs7.existsSync(path61.join(projectRoot, name)));
|
|
8240
8393
|
if (!prettierConfigFile) {
|
|
8241
8394
|
report3(
|
|
8242
8395
|
"No prettier config found. Create one that takes its configuration from zirka (styleguide({ prettier: true }).prettierConfig)."
|
|
8243
8396
|
);
|
|
8244
8397
|
} else {
|
|
8245
|
-
const content = fs7.readFileSync(
|
|
8398
|
+
const content = fs7.readFileSync(path61.join(projectRoot, prettierConfigFile), "utf8");
|
|
8246
8399
|
if (!content.includes("zirka")) {
|
|
8247
8400
|
report3(
|
|
8248
8401
|
"The prettier config must take its configuration from zirka (styleguide({ prettier: true }).prettierConfig) instead of restating it locally."
|
|
@@ -8263,36 +8416,36 @@ function referencesZirka(sourceCode) {
|
|
|
8263
8416
|
}
|
|
8264
8417
|
|
|
8265
8418
|
// eslint/rules/zod-fetch-helper.ts
|
|
8266
|
-
var
|
|
8267
|
-
var
|
|
8268
|
-
var
|
|
8269
|
-
var FETCHED = `fetch must not be called; make the request through ${
|
|
8270
|
-
var
|
|
8271
|
-
var
|
|
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}`;
|
|
8272
8425
|
var GLOBAL_OBJECTS = /* @__PURE__ */ new Set(["globalThis", "window", "self", "global"]);
|
|
8273
|
-
var
|
|
8274
|
-
function
|
|
8426
|
+
var TEST_FILE2 = /(?:^|[\\/])(?:__tests__|tests)[\\/]|[.](?:test|spec)[.][cm]?[jt]sx?$/;
|
|
8427
|
+
function isNamed4(node, name) {
|
|
8275
8428
|
return node?.type === "Identifier" && node.name === name;
|
|
8276
8429
|
}
|
|
8277
8430
|
function callsFetch(callee) {
|
|
8278
|
-
if (
|
|
8279
|
-
return callee.type === "MemberExpression" && !callee.computed &&
|
|
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);
|
|
8280
8433
|
}
|
|
8281
8434
|
var zodFetchHelperRule = {
|
|
8282
8435
|
meta: {
|
|
8283
8436
|
schema: [],
|
|
8284
8437
|
type: "problem",
|
|
8285
8438
|
docs: {
|
|
8286
|
-
description: `Require every request to go through the ${
|
|
8439
|
+
description: `Require every request to go through the ${HELPER4} imported from ${ENTRY4}, the only caller of fetch.`
|
|
8287
8440
|
}
|
|
8288
8441
|
},
|
|
8289
8442
|
create(context) {
|
|
8290
|
-
if (
|
|
8443
|
+
if (TEST_FILE2.test(context.filename)) return {};
|
|
8291
8444
|
const checkSource = (node) => {
|
|
8292
|
-
if (!node.source || node.source.value ===
|
|
8445
|
+
if (!node.source || node.source.value === ENTRY4) return;
|
|
8293
8446
|
for (const specifier of node.specifiers) {
|
|
8294
|
-
if (!
|
|
8295
|
-
context.report({ node: specifier, message:
|
|
8447
|
+
if (!isNamed4(specifier.local, HELPER4)) continue;
|
|
8448
|
+
context.report({ node: specifier, message: IMPORTED4 });
|
|
8296
8449
|
}
|
|
8297
8450
|
};
|
|
8298
8451
|
return {
|
|
@@ -8301,11 +8454,11 @@ var zodFetchHelperRule = {
|
|
|
8301
8454
|
context.report({ node, message: FETCHED });
|
|
8302
8455
|
},
|
|
8303
8456
|
FunctionDeclaration(node) {
|
|
8304
|
-
if (
|
|
8457
|
+
if (isNamed4(node.id, HELPER4)) context.report({ node, message: DECLARED4 });
|
|
8305
8458
|
},
|
|
8306
8459
|
VariableDeclarator(node) {
|
|
8307
|
-
if (
|
|
8308
|
-
context.report({ node, message:
|
|
8460
|
+
if (isNamed4(node.id.type === "Identifier" ? node.id : null, HELPER4)) {
|
|
8461
|
+
context.report({ node, message: DECLARED4 });
|
|
8309
8462
|
}
|
|
8310
8463
|
},
|
|
8311
8464
|
ImportDeclaration: checkSource,
|
|
@@ -8437,6 +8590,7 @@ function assertTypescriptAlignment() {
|
|
|
8437
8590
|
// eslint/index.ts
|
|
8438
8591
|
var pasikaNextjsAppRules = {
|
|
8439
8592
|
// Framework-agnostic TypeScript rules.
|
|
8593
|
+
"api-contract": apiContractRule,
|
|
8440
8594
|
"file-length": fileLengthRule,
|
|
8441
8595
|
"filename-case": filenameCaseRule,
|
|
8442
8596
|
"import-boundaries": importBoundariesRule,
|