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