@sarj/eslint-plugin 15.14.0 → 15.15.0
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/index.cjs +1235 -667
- package/dist/index.d.cts +31 -3
- package/dist/index.d.ts +31 -3
- package/dist/index.js +1211 -643
- package/package.json +3 -2
package/dist/index.js
CHANGED
|
@@ -1223,8 +1223,8 @@ function testCallMatrixStems(comments) {
|
|
|
1223
1223
|
const stems = /* @__PURE__ */ new Set();
|
|
1224
1224
|
for (const comment of comments) {
|
|
1225
1225
|
const body2 = stripCommentMarker(comment.value);
|
|
1226
|
-
const
|
|
1227
|
-
if (
|
|
1226
|
+
const stem4 = CALL_LABEL_RE.exec(body2)?.[1];
|
|
1227
|
+
if (stem4 !== void 0 && MULTIPLIER_PSEUDOCODE_RE.test(body2)) stems.add(stem4);
|
|
1228
1228
|
}
|
|
1229
1229
|
return stems;
|
|
1230
1230
|
}
|
|
@@ -4883,8 +4883,8 @@ var CJS_OBJECT_EXPORT_METHODS = /* @__PURE__ */ new Set(["assign", "defineProper
|
|
|
4883
4883
|
function fileParts(filename) {
|
|
4884
4884
|
const base = filename.replaceAll("\\", "/").split("/").at(-1) ?? "";
|
|
4885
4885
|
const extension = base.match(/(\.[cm]?[jt]sx?)$/u)?.[1] ?? ".ts";
|
|
4886
|
-
const [
|
|
4887
|
-
return { stem:
|
|
4886
|
+
const [stem4 = "", ...suffixes] = base.slice(0, -extension.length).split(".");
|
|
4887
|
+
return { stem: stem4, suffixes: suffixes.map((suffix) => suffix.toLowerCase()) };
|
|
4888
4888
|
}
|
|
4889
4889
|
function declaredNames(declaration) {
|
|
4890
4890
|
if (declaration.declare === true) return [];
|
|
@@ -5008,8 +5008,8 @@ var no_generic_single_export_module_default = createRule({
|
|
|
5008
5008
|
defaultOptions: [],
|
|
5009
5009
|
create(context) {
|
|
5010
5010
|
const file = fileParts(context.filename);
|
|
5011
|
-
const { stem:
|
|
5012
|
-
if (!GENERIC_STEMS.has(
|
|
5011
|
+
const { stem: stem4 } = file;
|
|
5012
|
+
if (!GENERIC_STEMS.has(stem4) || isTestFile(context.filename) || isGeneratedFile(context.filename, context.sourceCode.text)) return {};
|
|
5013
5013
|
let hasCommonJsExport = false;
|
|
5014
5014
|
return {
|
|
5015
5015
|
CallExpression(node) {
|
|
@@ -5029,12 +5029,12 @@ var no_generic_single_export_module_default = createRule({
|
|
|
5029
5029
|
const { name: exported, node } = onlyExport;
|
|
5030
5030
|
if (isConventionalFrameworkUtility(context.filename, exported)) return;
|
|
5031
5031
|
const exportedRole = exported.replaceAll(/[^a-z0-9]/giu, "").toLowerCase();
|
|
5032
|
-
const pathRole = [
|
|
5032
|
+
const pathRole = [stem4, ...file.suffixes].join("").replaceAll(/[^a-z0-9]/giu, "");
|
|
5033
5033
|
if (exportedRole === pathRole && file.suffixes.length > 0) return;
|
|
5034
5034
|
context.report({
|
|
5035
5035
|
node,
|
|
5036
5036
|
messageId: "genericSingleExport",
|
|
5037
|
-
data: { stem:
|
|
5037
|
+
data: { stem: stem4, exported }
|
|
5038
5038
|
});
|
|
5039
5039
|
}
|
|
5040
5040
|
};
|
|
@@ -5351,7 +5351,7 @@ var no_positional_tuple_return_default = createRule({
|
|
|
5351
5351
|
const aliases = typeAliases(context.sourceCode.ast);
|
|
5352
5352
|
const reportedFunctions = /* @__PURE__ */ new WeakSet();
|
|
5353
5353
|
const functionStack = [];
|
|
5354
|
-
const
|
|
5354
|
+
const report2 = (annotation, name) => {
|
|
5355
5355
|
const tuple = tupleReturnType(annotation, aliases);
|
|
5356
5356
|
if (tuple === null || tuple.elementTypes.length < MIN_ELEMENTS) return;
|
|
5357
5357
|
context.report({
|
|
@@ -5385,7 +5385,7 @@ var no_positional_tuple_return_default = createRule({
|
|
|
5385
5385
|
if (name === null) {
|
|
5386
5386
|
return;
|
|
5387
5387
|
}
|
|
5388
|
-
|
|
5388
|
+
report2(annotation, name);
|
|
5389
5389
|
};
|
|
5390
5390
|
const enterFunction = (node) => {
|
|
5391
5391
|
functionStack.push(node);
|
|
@@ -5410,34 +5410,34 @@ var no_positional_tuple_return_default = createRule({
|
|
|
5410
5410
|
},
|
|
5411
5411
|
TSDeclareFunction(node) {
|
|
5412
5412
|
if (node.id === null || node.returnType === void 0 || node.parent.type !== AST_NODE_TYPES21.ExportNamedDeclaration && node.parent.type !== AST_NODE_TYPES21.ExportDefaultDeclaration && !specifierExports.has(node.id.name)) return;
|
|
5413
|
-
|
|
5413
|
+
report2(node.returnType.typeAnnotation, node.id.name);
|
|
5414
5414
|
},
|
|
5415
5415
|
TSCallSignatureDeclaration(node) {
|
|
5416
5416
|
const owner = owningInterface(node);
|
|
5417
5417
|
if (owner === null || !isExportedInterface(owner, typeExports) || node.returnType === void 0) return;
|
|
5418
|
-
|
|
5418
|
+
report2(node.returnType.typeAnnotation, `${owner.id.name}.call`);
|
|
5419
5419
|
},
|
|
5420
5420
|
TSMethodSignature(node) {
|
|
5421
5421
|
const owner = owningInterface(node);
|
|
5422
5422
|
const alias = owningTypeAlias(node);
|
|
5423
|
-
const
|
|
5424
|
-
if ((owner === null || !isExportedInterface(owner, typeExports)) && (alias === null || !typeExports.has(alias.id.name)) || node.returnType === void 0 ||
|
|
5425
|
-
|
|
5423
|
+
const memberName5 = staticMemberName3(node.key);
|
|
5424
|
+
if ((owner === null || !isExportedInterface(owner, typeExports)) && (alias === null || !typeExports.has(alias.id.name)) || node.returnType === void 0 || memberName5 === null) return;
|
|
5425
|
+
report2(node.returnType.typeAnnotation, `${owner?.id.name ?? alias?.id.name ?? "type"}.${memberName5}`);
|
|
5426
5426
|
},
|
|
5427
5427
|
TSTypeAliasDeclaration(node) {
|
|
5428
5428
|
if (!typeExports.has(node.id.name)) return;
|
|
5429
5429
|
const returnType = callableReturnType(node.typeAnnotation, aliases);
|
|
5430
|
-
if (returnType !== null)
|
|
5430
|
+
if (returnType !== null) report2(returnType, node.id.name);
|
|
5431
5431
|
},
|
|
5432
5432
|
TSPropertySignature(node) {
|
|
5433
5433
|
const owner = owningInterface(node);
|
|
5434
5434
|
const alias = owningTypeAlias(node);
|
|
5435
5435
|
const annotation = node.typeAnnotation?.typeAnnotation;
|
|
5436
|
-
const
|
|
5437
|
-
if ((owner === null || !isExportedInterface(owner, typeExports)) && (alias === null || !typeExports.has(alias.id.name)) ||
|
|
5436
|
+
const memberName5 = staticMemberName3(node.key);
|
|
5437
|
+
if ((owner === null || !isExportedInterface(owner, typeExports)) && (alias === null || !typeExports.has(alias.id.name)) || memberName5 === null || annotation === void 0) return;
|
|
5438
5438
|
const returnType = callableReturnType(annotation, aliases);
|
|
5439
5439
|
if (returnType !== null) {
|
|
5440
|
-
|
|
5440
|
+
report2(returnType, `${owner?.id.name ?? alias?.id.name ?? "type"}.${memberName5}`);
|
|
5441
5441
|
}
|
|
5442
5442
|
},
|
|
5443
5443
|
PropertyDefinition(node) {
|
|
@@ -5448,7 +5448,7 @@ var no_positional_tuple_return_default = createRule({
|
|
|
5448
5448
|
const returnType = callableReturnType(annotation, aliases);
|
|
5449
5449
|
if (returnType !== null) {
|
|
5450
5450
|
const name = node.key.type === AST_NODE_TYPES21.Identifier ? node.key.name : "property";
|
|
5451
|
-
|
|
5451
|
+
report2(returnType, name);
|
|
5452
5452
|
}
|
|
5453
5453
|
}
|
|
5454
5454
|
};
|
|
@@ -5924,7 +5924,7 @@ var no_restricted_library_load_default = createRule({
|
|
|
5924
5924
|
defaultOptions: [{ libraries: [] }],
|
|
5925
5925
|
create(context, [options]) {
|
|
5926
5926
|
const restrictions = options.libraries;
|
|
5927
|
-
function
|
|
5927
|
+
function report2(node, source) {
|
|
5928
5928
|
const restriction = restrictions.find(
|
|
5929
5929
|
(entry) => matchesModule(source, entry.module)
|
|
5930
5930
|
);
|
|
@@ -5950,7 +5950,7 @@ var no_restricted_library_load_default = createRule({
|
|
|
5950
5950
|
return {
|
|
5951
5951
|
ImportExpression(node) {
|
|
5952
5952
|
const source = literalModule(node.source);
|
|
5953
|
-
if (source !== null)
|
|
5953
|
+
if (source !== null) report2(node.source, source);
|
|
5954
5954
|
},
|
|
5955
5955
|
CallExpression(node) {
|
|
5956
5956
|
let requireIdentifier = null;
|
|
@@ -5961,12 +5961,12 @@ var no_restricted_library_load_default = createRule({
|
|
|
5961
5961
|
}
|
|
5962
5962
|
if (requireIdentifier === null || !isUnshadowedRequire(requireIdentifier)) return;
|
|
5963
5963
|
const source = literalModule(node.arguments[0]);
|
|
5964
|
-
if (source !== null)
|
|
5964
|
+
if (source !== null) report2(node.arguments[0], source);
|
|
5965
5965
|
},
|
|
5966
5966
|
TSImportEqualsDeclaration(node) {
|
|
5967
5967
|
if (node.moduleReference.type !== AST_NODE_TYPES23.TSExternalModuleReference) return;
|
|
5968
5968
|
const source = literalModule(node.moduleReference.expression);
|
|
5969
|
-
if (source !== null)
|
|
5969
|
+
if (source !== null) report2(node.moduleReference.expression, source);
|
|
5970
5970
|
}
|
|
5971
5971
|
};
|
|
5972
5972
|
}
|
|
@@ -7782,7 +7782,7 @@ var no_sleep_in_test_body_default = createRule({
|
|
|
7782
7782
|
if (!isTestFile(context.filename)) {
|
|
7783
7783
|
return {};
|
|
7784
7784
|
}
|
|
7785
|
-
const
|
|
7785
|
+
const report2 = (node) => {
|
|
7786
7786
|
if (!isImmediatelyConsumedSleep(node)) {
|
|
7787
7787
|
return;
|
|
7788
7788
|
}
|
|
@@ -7795,12 +7795,12 @@ var no_sleep_in_test_body_default = createRule({
|
|
|
7795
7795
|
return {
|
|
7796
7796
|
NewExpression(node) {
|
|
7797
7797
|
if (isPromiseSleep(node)) {
|
|
7798
|
-
|
|
7798
|
+
report2(node);
|
|
7799
7799
|
}
|
|
7800
7800
|
},
|
|
7801
7801
|
CallExpression(node) {
|
|
7802
7802
|
if (isHelperSleep(node)) {
|
|
7803
|
-
|
|
7803
|
+
report2(node);
|
|
7804
7804
|
}
|
|
7805
7805
|
}
|
|
7806
7806
|
};
|
|
@@ -10251,7 +10251,7 @@ function reportClass2(context, services, owner) {
|
|
|
10251
10251
|
}
|
|
10252
10252
|
function isConvertible(member) {
|
|
10253
10253
|
if (member.type !== AST_NODE_TYPES43.MethodDefinition && member.type !== AST_NODE_TYPES43.PropertyDefinition && member.type !== AST_NODE_TYPES43.AccessorProperty) return false;
|
|
10254
|
-
return member.accessibility === "private" && !member.computed && member.key.type === AST_NODE_TYPES43.Identifier && member.decorators.length === 0 && !("declare" in member && member.declare) && !member.override && !(member.type === AST_NODE_TYPES43.MethodDefinition && member.value.body === null);
|
|
10254
|
+
return member.accessibility === "private" && !(member.type === AST_NODE_TYPES43.MethodDefinition && member.kind === "constructor") && !member.computed && member.key.type === AST_NODE_TYPES43.Identifier && member.decorators.length === 0 && !("declare" in member && member.declare) && !member.override && !(member.type === AST_NODE_TYPES43.MethodDefinition && member.value.body === null);
|
|
10255
10255
|
}
|
|
10256
10256
|
var prefer_ecmascript_private_members_default = createRule({
|
|
10257
10257
|
name: "prefer-ecmascript-private-members",
|
|
@@ -10449,9 +10449,9 @@ var INPUT_MODULE = /(?:^|\/)components\/ui\/input$/u;
|
|
|
10449
10449
|
var INPUT_GROUP_MODULE = /(?:^|\/)components\/ui\/input-group$/u;
|
|
10450
10450
|
var MAX_JSX_DISTANCE = 2;
|
|
10451
10451
|
var SEARCH_EXPORTS = ["Search", "SearchIcon", "LucideSearch"];
|
|
10452
|
-
function localNamedImports(node,
|
|
10452
|
+
function localNamedImports(node, importedName7) {
|
|
10453
10453
|
return node.specifiers.filter(
|
|
10454
|
-
(specifier) => specifier.type === AST_NODE_TYPES45.ImportSpecifier && (specifier.imported.type === AST_NODE_TYPES45.Identifier ? specifier.imported.name : specifier.imported.value) ===
|
|
10454
|
+
(specifier) => specifier.type === AST_NODE_TYPES45.ImportSpecifier && (specifier.imported.type === AST_NODE_TYPES45.Identifier ? specifier.imported.name : specifier.imported.value) === importedName7
|
|
10455
10455
|
).map((specifier) => specifier.local.name);
|
|
10456
10456
|
}
|
|
10457
10457
|
function elementName(node) {
|
|
@@ -11664,8 +11664,67 @@ var prefer_module_level_schema_default = createRule({
|
|
|
11664
11664
|
}
|
|
11665
11665
|
});
|
|
11666
11666
|
|
|
11667
|
+
// src/rules/prefer-named-complex-return-type.ts
|
|
11668
|
+
import { AST_NODE_TYPES as AST_NODE_TYPES50 } from "@typescript-eslint/utils";
|
|
11669
|
+
var PREFER_NAMED_COMPLEX_RETURN_TYPE_DOCUMENTATION = {
|
|
11670
|
+
summary: "Prefer a named contract for structurally complex function return types.",
|
|
11671
|
+
rationale: "A large inline return annotation hides a reusable domain concept and makes signatures difficult to scan.",
|
|
11672
|
+
remediation: "Extract the return annotation to a named type or interface and reference that contract from the signature.",
|
|
11673
|
+
category: "maintainability",
|
|
11674
|
+
limitations: [
|
|
11675
|
+
"Only explicit object types with at least three members and unions with at least three object variants are reported.",
|
|
11676
|
+
"Generic wrappers such as Promise and Readonly are unwrapped one level at a time; inferred return types are outside this rule."
|
|
11677
|
+
],
|
|
11678
|
+
examples: [
|
|
11679
|
+
{ id: "named-result", title: "Name a multi-state result", outcome: "no-match", files: [{ path: "src/queue.ts", source: "type ClaimResult = { state: 'idle' } | { state: 'waiting'; retryAt: number } | { state: 'claimed'; id: string }; export function claim(): ClaimResult { return { state: 'idle' }; }" }], focusPath: "src/queue.ts", expectedCount: 0, public: true },
|
|
11680
|
+
{ id: "inline-result", title: "Do not inline a multi-state result", outcome: "match", files: [{ path: "src/queue.ts", source: "export function claim(): { state: 'idle' } | { state: 'waiting'; retryAt: number } | { state: 'claimed'; id: string } { return { state: 'idle' }; }" }], focusPath: "src/queue.ts", expectedCount: 1, public: true }
|
|
11681
|
+
]
|
|
11682
|
+
};
|
|
11683
|
+
function unwrap4(node) {
|
|
11684
|
+
if (node.type === AST_NODE_TYPES50.TSTypeReference && node.typeArguments?.params.length === 1) {
|
|
11685
|
+
const [inner] = node.typeArguments.params;
|
|
11686
|
+
if (inner !== void 0) return unwrap4(inner);
|
|
11687
|
+
}
|
|
11688
|
+
return node;
|
|
11689
|
+
}
|
|
11690
|
+
function report(context, node) {
|
|
11691
|
+
const annotation = node.returnType?.typeAnnotation;
|
|
11692
|
+
if (annotation !== void 0 && isComplex(annotation)) {
|
|
11693
|
+
context.report({ node: annotation, messageId: "nameComplexReturnType" });
|
|
11694
|
+
}
|
|
11695
|
+
}
|
|
11696
|
+
function isComplex(node) {
|
|
11697
|
+
const type = unwrap4(node);
|
|
11698
|
+
if (type.type === AST_NODE_TYPES50.TSTypeLiteral) return type.members.length >= 3;
|
|
11699
|
+
if (type.type !== AST_NODE_TYPES50.TSUnionType || type.types.length < 3) return false;
|
|
11700
|
+
return type.types.every((member) => unwrap4(member).type === AST_NODE_TYPES50.TSTypeLiteral);
|
|
11701
|
+
}
|
|
11702
|
+
var prefer_named_complex_return_type_default = createRule({
|
|
11703
|
+
name: "prefer-named-complex-return-type",
|
|
11704
|
+
documentation: PREFER_NAMED_COMPLEX_RETURN_TYPE_DOCUMENTATION,
|
|
11705
|
+
meta: {
|
|
11706
|
+
type: "suggestion",
|
|
11707
|
+
docs: { description: "Prefer a named contract for structurally complex function return types." },
|
|
11708
|
+
schema: [],
|
|
11709
|
+
messages: {
|
|
11710
|
+
nameComplexReturnType: "Extract this structurally complex return annotation to a named type or interface."
|
|
11711
|
+
}
|
|
11712
|
+
},
|
|
11713
|
+
defaultOptions: [],
|
|
11714
|
+
create(context) {
|
|
11715
|
+
if (isTestFile(context.filename) || isGeneratedFile(context.filename, context.sourceCode.text)) return {};
|
|
11716
|
+
return {
|
|
11717
|
+
ArrowFunctionExpression: (node) => report(context, node),
|
|
11718
|
+
FunctionDeclaration: (node) => report(context, node),
|
|
11719
|
+
FunctionExpression: (node) => report(context, node),
|
|
11720
|
+
TSDeclareFunction: (node) => report(context, node),
|
|
11721
|
+
TSMethodSignature: (node) => report(context, node)
|
|
11722
|
+
};
|
|
11723
|
+
}
|
|
11724
|
+
});
|
|
11725
|
+
|
|
11667
11726
|
// src/rules/prefer-native-random-uuid.ts
|
|
11668
|
-
import { AST_NODE_TYPES as
|
|
11727
|
+
import { AST_NODE_TYPES as AST_NODE_TYPES51, ASTUtils as ASTUtils14 } from "@typescript-eslint/utils";
|
|
11669
11728
|
var PREFER_NATIVE_RANDOM_UUID_DOCUMENTATION = {
|
|
11670
11729
|
summary: "Prefer `globalThis.crypto.randomUUID()` over resolved zero-argument UUID v4 bindings from the `uuid` package.",
|
|
11671
11730
|
rationale: "The platform implementation avoids an unnecessary dependency for standard random UUID generation.",
|
|
@@ -11679,7 +11738,7 @@ var PREFER_NATIVE_RANDOM_UUID_DOCUMENTATION = {
|
|
|
11679
11738
|
]
|
|
11680
11739
|
};
|
|
11681
11740
|
function requireUuid(node) {
|
|
11682
|
-
return node?.type ===
|
|
11741
|
+
return node?.type === AST_NODE_TYPES51.CallExpression && node.callee.type === AST_NODE_TYPES51.Identifier && node.callee.name === "require" && node.arguments.length === 1 && node.arguments[0]?.type === AST_NODE_TYPES51.Literal && node.arguments[0].value === "uuid";
|
|
11683
11742
|
}
|
|
11684
11743
|
var prefer_native_random_uuid_default = createRule({
|
|
11685
11744
|
name: "prefer-native-random-uuid",
|
|
@@ -11707,7 +11766,7 @@ var prefer_native_random_uuid_default = createRule({
|
|
|
11707
11766
|
const variable = resolve(identifier);
|
|
11708
11767
|
if (variable !== null) destination.add(variable);
|
|
11709
11768
|
}
|
|
11710
|
-
function
|
|
11769
|
+
function report2(node) {
|
|
11711
11770
|
context.report({
|
|
11712
11771
|
node,
|
|
11713
11772
|
messageId: "preferNative",
|
|
@@ -11723,48 +11782,179 @@ var prefer_native_random_uuid_default = createRule({
|
|
|
11723
11782
|
ImportDeclaration(node) {
|
|
11724
11783
|
if (node.source.value !== "uuid") return;
|
|
11725
11784
|
for (const specifier of node.specifiers) {
|
|
11726
|
-
if (specifier.type ===
|
|
11785
|
+
if (specifier.type === AST_NODE_TYPES51.ImportSpecifier && (specifier.imported.type === AST_NODE_TYPES51.Identifier ? specifier.imported.name === "v4" : specifier.imported.value === "v4")) {
|
|
11727
11786
|
record(specifier.local, directBindings);
|
|
11728
|
-
} else if (specifier.type ===
|
|
11787
|
+
} else if (specifier.type === AST_NODE_TYPES51.ImportNamespaceSpecifier) {
|
|
11729
11788
|
record(specifier.local, namespaceBindings);
|
|
11730
11789
|
}
|
|
11731
11790
|
}
|
|
11732
11791
|
},
|
|
11733
11792
|
VariableDeclarator(node) {
|
|
11734
11793
|
if (node.parent.kind !== "const" || !requireUuid(node.init)) return;
|
|
11735
|
-
if (node.init?.type !==
|
|
11794
|
+
if (node.init?.type !== AST_NODE_TYPES51.CallExpression || node.init.callee.type !== AST_NODE_TYPES51.Identifier || (resolve(node.init.callee)?.defs.length ?? 0) > 0) {
|
|
11736
11795
|
return;
|
|
11737
11796
|
}
|
|
11738
|
-
if (node.id.type ===
|
|
11797
|
+
if (node.id.type === AST_NODE_TYPES51.Identifier) {
|
|
11739
11798
|
record(node.id, namespaceBindings);
|
|
11740
11799
|
return;
|
|
11741
11800
|
}
|
|
11742
|
-
if (node.id.type !==
|
|
11801
|
+
if (node.id.type !== AST_NODE_TYPES51.ObjectPattern) return;
|
|
11743
11802
|
for (const property of node.id.properties) {
|
|
11744
|
-
if (property.type ===
|
|
11803
|
+
if (property.type === AST_NODE_TYPES51.Property && !property.computed && (property.key.type === AST_NODE_TYPES51.Identifier && property.key.name === "v4" || property.key.type === AST_NODE_TYPES51.Literal && property.key.value === "v4") && property.value.type === AST_NODE_TYPES51.Identifier) {
|
|
11745
11804
|
record(property.value, directBindings);
|
|
11746
11805
|
}
|
|
11747
11806
|
}
|
|
11748
11807
|
},
|
|
11749
11808
|
"CallExpression:exit"(node) {
|
|
11750
11809
|
if (node.arguments.length !== 0) return;
|
|
11751
|
-
if (node.callee.type ===
|
|
11810
|
+
if (node.callee.type === AST_NODE_TYPES51.Identifier) {
|
|
11752
11811
|
const variable2 = resolve(node.callee);
|
|
11753
|
-
if (variable2 !== null && directBindings.has(variable2))
|
|
11812
|
+
if (variable2 !== null && directBindings.has(variable2)) report2(node);
|
|
11754
11813
|
return;
|
|
11755
11814
|
}
|
|
11756
|
-
if (node.callee.type !==
|
|
11815
|
+
if (node.callee.type !== AST_NODE_TYPES51.MemberExpression || node.callee.computed || node.callee.object.type !== AST_NODE_TYPES51.Identifier || node.callee.property.type !== AST_NODE_TYPES51.Identifier || node.callee.property.name !== "v4") {
|
|
11757
11816
|
return;
|
|
11758
11817
|
}
|
|
11759
11818
|
const variable = resolve(node.callee.object);
|
|
11760
|
-
if (variable !== null && namespaceBindings.has(variable))
|
|
11819
|
+
if (variable !== null && namespaceBindings.has(variable)) report2(node);
|
|
11820
|
+
}
|
|
11821
|
+
};
|
|
11822
|
+
}
|
|
11823
|
+
});
|
|
11824
|
+
|
|
11825
|
+
// src/rules/prefer-node-crypto-hash.ts
|
|
11826
|
+
import { AST_NODE_TYPES as AST_NODE_TYPES52 } from "@typescript-eslint/utils";
|
|
11827
|
+
var PREFER_NODE_CRYPTO_HASH_DOCUMENTATION = {
|
|
11828
|
+
summary: "Prefer the modern one-shot node:crypto hash API when streaming state is unnecessary.",
|
|
11829
|
+
rationale: "A createHash-update-digest chain allocates mutable streaming state for a single in-memory value; Node's built-in hash function expresses the one-shot operation directly and can use its optimized fast path.",
|
|
11830
|
+
remediation: "Import hash from node:crypto and replace a single-update chain with hash(algorithm, value, encoding). Keep createHash for streams or multiple incremental updates.",
|
|
11831
|
+
category: "performance",
|
|
11832
|
+
limitations: [
|
|
11833
|
+
"Only direct ESM imports and namespace imports from node:crypto are analyzed.",
|
|
11834
|
+
"Only a literal algorithm with exactly one update call is reported; streaming and incremental hashes remain valid."
|
|
11835
|
+
],
|
|
11836
|
+
examples: [
|
|
11837
|
+
{ id: "one-shot-hash", title: "Use Node's one-shot hash API", outcome: "no-match", files: [{ path: "case.ts", source: "import { hash } from 'node:crypto'; export const digest = hash('sha256', 'value', 'hex');" }], focusPath: "case.ts", expectedCount: 0, public: true },
|
|
11838
|
+
{ id: "mutable-one-shot-chain", title: "Avoid mutable state for one value", outcome: "match", files: [{ path: "case.ts", source: "import { createHash } from 'node:crypto'; export const digest = createHash('sha256').update('value').digest('hex');" }], focusPath: "case.ts", expectedCount: 1, public: true }
|
|
11839
|
+
]
|
|
11840
|
+
};
|
|
11841
|
+
var prefer_node_crypto_hash_default = createRule({
|
|
11842
|
+
name: "prefer-node-crypto-hash",
|
|
11843
|
+
documentation: PREFER_NODE_CRYPTO_HASH_DOCUMENTATION,
|
|
11844
|
+
meta: { type: "problem", docs: { description: PREFER_NODE_CRYPTO_HASH_DOCUMENTATION.summary }, schema: [], messages: { preferNodeCryptoHash: "Prefer the modern one-shot node:crypto hash API when streaming state is unnecessary." } },
|
|
11845
|
+
defaultOptions: [],
|
|
11846
|
+
create(context) {
|
|
11847
|
+
const directImports = /* @__PURE__ */ new Set();
|
|
11848
|
+
const namespaceImports = /* @__PURE__ */ new Set();
|
|
11849
|
+
return {
|
|
11850
|
+
ImportDeclaration(node) {
|
|
11851
|
+
if (node.source.value !== "node:crypto") return;
|
|
11852
|
+
for (const specifier of node.specifiers) {
|
|
11853
|
+
if (specifier.type === AST_NODE_TYPES52.ImportNamespaceSpecifier) {
|
|
11854
|
+
namespaceImports.add(specifier.local.name);
|
|
11855
|
+
} else if (specifier.type === AST_NODE_TYPES52.ImportSpecifier && importedName5(specifier.imported) === "createHash") {
|
|
11856
|
+
directImports.add(specifier.local.name);
|
|
11857
|
+
}
|
|
11858
|
+
}
|
|
11859
|
+
},
|
|
11860
|
+
CallExpression(node) {
|
|
11861
|
+
if (!isMemberCall(node, "digest")) return;
|
|
11862
|
+
const update = node.callee.object;
|
|
11863
|
+
if (update.type !== AST_NODE_TYPES52.CallExpression || update.arguments.length !== 1 || !isMemberCall(update, "update"))
|
|
11864
|
+
return;
|
|
11865
|
+
const create = update.callee.object;
|
|
11866
|
+
if (create.type !== AST_NODE_TYPES52.CallExpression || create.arguments.length !== 1 || create.arguments[0]?.type !== AST_NODE_TYPES52.Literal || typeof create.arguments[0].value !== "string" || !isCreateHashCall(create, directImports, namespaceImports))
|
|
11867
|
+
return;
|
|
11868
|
+
context.report({ node, messageId: "preferNodeCryptoHash" });
|
|
11869
|
+
}
|
|
11870
|
+
};
|
|
11871
|
+
}
|
|
11872
|
+
});
|
|
11873
|
+
function importedName5(node) {
|
|
11874
|
+
return node.type === AST_NODE_TYPES52.Identifier ? node.name : node.value;
|
|
11875
|
+
}
|
|
11876
|
+
function isMemberCall(node, name) {
|
|
11877
|
+
return node.callee.type === AST_NODE_TYPES52.MemberExpression && !node.callee.computed && node.callee.property.type === AST_NODE_TYPES52.Identifier && node.callee.property.name === name;
|
|
11878
|
+
}
|
|
11879
|
+
function isCreateHashCall(node, directImports, namespaceImports) {
|
|
11880
|
+
if (node.callee.type === AST_NODE_TYPES52.Identifier)
|
|
11881
|
+
return directImports.has(node.callee.name);
|
|
11882
|
+
return node.callee.type === AST_NODE_TYPES52.MemberExpression && !node.callee.computed && node.callee.object.type === AST_NODE_TYPES52.Identifier && namespaceImports.has(node.callee.object.name) && node.callee.property.type === AST_NODE_TYPES52.Identifier && node.callee.property.name === "createHash";
|
|
11883
|
+
}
|
|
11884
|
+
|
|
11885
|
+
// src/rules/prefer-node-fs-promises.ts
|
|
11886
|
+
import { AST_NODE_TYPES as AST_NODE_TYPES53 } from "@typescript-eslint/utils";
|
|
11887
|
+
var PREFER_NODE_FS_PROMISES_DOCUMENTATION = {
|
|
11888
|
+
summary: "Prefer promise-based Node.js filesystem APIs over synchronous calls in production modules.",
|
|
11889
|
+
rationale: "Synchronous filesystem work blocks the event loop and can stall unrelated daemon, server, and worker tasks.",
|
|
11890
|
+
remediation: "Import the promise API from node:fs/promises and await it; use FileHandle.sync only where a documented durability boundary requires it.",
|
|
11891
|
+
category: "performance",
|
|
11892
|
+
limitations: [
|
|
11893
|
+
"Tests and generated files are excluded.",
|
|
11894
|
+
"ESLint rule implementations under src/rules are excluded because visitor creation and execution are synchronous by contract.",
|
|
11895
|
+
"The rule covers static ESM imports and member calls through namespace/default imports from node:fs; CommonJS require flows are not inferred."
|
|
11896
|
+
],
|
|
11897
|
+
examples: [
|
|
11898
|
+
{ id: "async-read", title: "Use the promise API", outcome: "no-match", files: [{ path: "src/store.ts", source: "import { readFile } from 'node:fs/promises'; export async function load(path: string) { return readFile(path, 'utf8'); }" }], focusPath: "src/store.ts", expectedCount: 0, public: true },
|
|
11899
|
+
{ id: "sync-read", title: "Do not block on a synchronous read", outcome: "match", files: [{ path: "src/store.ts", source: "import { readFileSync } from 'node:fs'; export function load(path: string) { return readFileSync(path, 'utf8'); }" }], focusPath: "src/store.ts", expectedCount: 1, public: true }
|
|
11900
|
+
]
|
|
11901
|
+
};
|
|
11902
|
+
function memberName3(node) {
|
|
11903
|
+
if (!node.computed && node.property.type === AST_NODE_TYPES53.Identifier) return node.property.name;
|
|
11904
|
+
if (node.computed && node.property.type === AST_NODE_TYPES53.Literal && typeof node.property.value === "string") {
|
|
11905
|
+
return node.property.value;
|
|
11906
|
+
}
|
|
11907
|
+
return null;
|
|
11908
|
+
}
|
|
11909
|
+
var prefer_node_fs_promises_default = createRule({
|
|
11910
|
+
name: "prefer-node-fs-promises",
|
|
11911
|
+
documentation: PREFER_NODE_FS_PROMISES_DOCUMENTATION,
|
|
11912
|
+
meta: {
|
|
11913
|
+
type: "suggestion",
|
|
11914
|
+
docs: { description: "Prefer promise-based Node.js filesystem APIs over synchronous calls in production modules." },
|
|
11915
|
+
schema: [],
|
|
11916
|
+
messages: {
|
|
11917
|
+
preferAsyncFs: "Node filesystem API `{{name}}` is synchronous; use the promise API and await it."
|
|
11918
|
+
}
|
|
11919
|
+
},
|
|
11920
|
+
defaultOptions: [],
|
|
11921
|
+
create(context) {
|
|
11922
|
+
const normalizedFilename = context.filename.replaceAll("\\", "/");
|
|
11923
|
+
if (isTestFile(context.filename) || isGeneratedFile(context.filename, context.sourceCode.text) || normalizedFilename.includes("src/rules/"))
|
|
11924
|
+
return {};
|
|
11925
|
+
const namespaces = /* @__PURE__ */ new Set();
|
|
11926
|
+
return {
|
|
11927
|
+
ImportDeclaration(node) {
|
|
11928
|
+
if (node.source.value !== "node:fs" && node.source.value !== "fs") return;
|
|
11929
|
+
const synchronousImports = [];
|
|
11930
|
+
for (const specifier of node.specifiers) {
|
|
11931
|
+
if (specifier.type === AST_NODE_TYPES53.ImportNamespaceSpecifier || specifier.type === AST_NODE_TYPES53.ImportDefaultSpecifier) {
|
|
11932
|
+
namespaces.add(specifier.local.name);
|
|
11933
|
+
continue;
|
|
11934
|
+
}
|
|
11935
|
+
if (specifier.type === AST_NODE_TYPES53.ImportSpecifier && specifier.imported.type === AST_NODE_TYPES53.Identifier && specifier.imported.name.endsWith("Sync")) synchronousImports.push(specifier.imported.name);
|
|
11936
|
+
}
|
|
11937
|
+
if (synchronousImports.length > 0) {
|
|
11938
|
+
context.report({
|
|
11939
|
+
node,
|
|
11940
|
+
messageId: "preferAsyncFs",
|
|
11941
|
+
data: { name: synchronousImports.join(", ") }
|
|
11942
|
+
});
|
|
11943
|
+
}
|
|
11944
|
+
},
|
|
11945
|
+
MemberExpression(node) {
|
|
11946
|
+
if (node.object.type !== AST_NODE_TYPES53.Identifier || !namespaces.has(node.object.name)) return;
|
|
11947
|
+
const name = memberName3(node);
|
|
11948
|
+
if (name?.endsWith("Sync") === true) {
|
|
11949
|
+
context.report({ node, messageId: "preferAsyncFs", data: { name } });
|
|
11950
|
+
}
|
|
11761
11951
|
}
|
|
11762
11952
|
};
|
|
11763
11953
|
}
|
|
11764
11954
|
});
|
|
11765
11955
|
|
|
11766
11956
|
// src/rules/prefer-non-nullable-collection.ts
|
|
11767
|
-
import { AST_NODE_TYPES as
|
|
11957
|
+
import { AST_NODE_TYPES as AST_NODE_TYPES54, ASTUtils as ASTUtils15 } from "@typescript-eslint/utils";
|
|
11768
11958
|
var PREFER_NON_NULLABLE_COLLECTION_DOCUMENTATION = {
|
|
11769
11959
|
summary: "Suggest non-null arrays only when local control flow proves the nullish state is equivalent to an empty collection.",
|
|
11770
11960
|
rationale: "A redundant nullish collection state spreads defaults and guards through consumers without carrying information.",
|
|
@@ -11780,33 +11970,33 @@ var ARRAY_TYPE_NAMES = /* @__PURE__ */ new Set(["Array", "ReadonlyArray"]);
|
|
|
11780
11970
|
function propertyName3(node) {
|
|
11781
11971
|
const key = node.key;
|
|
11782
11972
|
if (node.computed) return null;
|
|
11783
|
-
if (key.type ===
|
|
11784
|
-
if (key.type ===
|
|
11973
|
+
if (key.type === AST_NODE_TYPES54.Identifier) return key.name;
|
|
11974
|
+
if (key.type === AST_NODE_TYPES54.Literal && typeof key.value === "string") return key.value;
|
|
11785
11975
|
return null;
|
|
11786
11976
|
}
|
|
11787
11977
|
function isArrayType(node) {
|
|
11788
|
-
if (node.type ===
|
|
11789
|
-
return node.type ===
|
|
11978
|
+
if (node.type === AST_NODE_TYPES54.TSArrayType) return true;
|
|
11979
|
+
return node.type === AST_NODE_TYPES54.TSTypeReference && node.typeName.type === AST_NODE_TYPES54.Identifier && ARRAY_TYPE_NAMES.has(node.typeName.name);
|
|
11790
11980
|
}
|
|
11791
11981
|
function nullableProperty(node) {
|
|
11792
11982
|
if (node.optional) return null;
|
|
11793
11983
|
const name = propertyName3(node);
|
|
11794
11984
|
const annotation = node.typeAnnotation?.typeAnnotation;
|
|
11795
|
-
if (name === null || annotation?.type !==
|
|
11985
|
+
if (name === null || annotation?.type !== AST_NODE_TYPES54.TSUnionType) return null;
|
|
11796
11986
|
const concrete = annotation.types.filter(
|
|
11797
|
-
(member) => member.type !==
|
|
11987
|
+
(member) => member.type !== AST_NODE_TYPES54.TSNullKeyword && member.type !== AST_NODE_TYPES54.TSUndefinedKeyword
|
|
11798
11988
|
);
|
|
11799
11989
|
if (concrete.length === 0 || !concrete.every(isArrayType)) return null;
|
|
11800
|
-
const acceptsNull = annotation.types.some((member) => member.type ===
|
|
11990
|
+
const acceptsNull = annotation.types.some((member) => member.type === AST_NODE_TYPES54.TSNullKeyword);
|
|
11801
11991
|
const acceptsUndefined = annotation.types.some(
|
|
11802
|
-
(member) => member.type ===
|
|
11992
|
+
(member) => member.type === AST_NODE_TYPES54.TSUndefinedKeyword
|
|
11803
11993
|
);
|
|
11804
11994
|
if (!acceptsNull && !acceptsUndefined) return null;
|
|
11805
11995
|
return { name, node, acceptsNull, acceptsUndefined };
|
|
11806
11996
|
}
|
|
11807
11997
|
function shapeProperties(members) {
|
|
11808
11998
|
return members.flatMap((member) => {
|
|
11809
|
-
if (member.type !==
|
|
11999
|
+
if (member.type !== AST_NODE_TYPES54.TSPropertySignature) return [];
|
|
11810
12000
|
const property = nullableProperty(member);
|
|
11811
12001
|
return property === null ? [] : [property];
|
|
11812
12002
|
});
|
|
@@ -11814,14 +12004,14 @@ function shapeProperties(members) {
|
|
|
11814
12004
|
function typeIndex(program) {
|
|
11815
12005
|
const index = /* @__PURE__ */ new Map();
|
|
11816
12006
|
for (const statement of program.body) {
|
|
11817
|
-
const exported = statement.type ===
|
|
12007
|
+
const exported = statement.type === AST_NODE_TYPES54.ExportNamedDeclaration;
|
|
11818
12008
|
const declaration = exported ? statement.declaration : statement;
|
|
11819
|
-
if (declaration?.type ===
|
|
12009
|
+
if (declaration?.type === AST_NODE_TYPES54.TSInterfaceDeclaration) {
|
|
11820
12010
|
index.set(declaration.id.name, {
|
|
11821
12011
|
exported,
|
|
11822
12012
|
properties: shapeProperties(declaration.body.body)
|
|
11823
12013
|
});
|
|
11824
|
-
} else if (declaration?.type ===
|
|
12014
|
+
} else if (declaration?.type === AST_NODE_TYPES54.TSTypeAliasDeclaration && declaration.typeAnnotation.type === AST_NODE_TYPES54.TSTypeLiteral) {
|
|
11825
12015
|
index.set(declaration.id.name, {
|
|
11826
12016
|
exported,
|
|
11827
12017
|
properties: shapeProperties(declaration.typeAnnotation.members)
|
|
@@ -11831,42 +12021,42 @@ function typeIndex(program) {
|
|
|
11831
12021
|
return index;
|
|
11832
12022
|
}
|
|
11833
12023
|
function emptyArray(node) {
|
|
11834
|
-
return node.type ===
|
|
12024
|
+
return node.type === AST_NODE_TYPES54.ArrayExpression && node.elements.length === 0;
|
|
11835
12025
|
}
|
|
11836
12026
|
function sameAccess(node, access) {
|
|
11837
12027
|
if (access.kind === "identifier") {
|
|
11838
|
-
return node.type ===
|
|
12028
|
+
return node.type === AST_NODE_TYPES54.Identifier && node.name === access.name;
|
|
11839
12029
|
}
|
|
11840
|
-
return node.type ===
|
|
12030
|
+
return node.type === AST_NODE_TYPES54.MemberExpression && !node.computed && node.object.type === AST_NODE_TYPES54.Identifier && node.object.name === access.object && node.property.type === AST_NODE_TYPES54.Identifier && node.property.name === access.property;
|
|
11841
12031
|
}
|
|
11842
12032
|
function isNullGuard(node, access) {
|
|
11843
|
-
if (node.type ===
|
|
11844
|
-
if (node.type !==
|
|
12033
|
+
if (node.type === AST_NODE_TYPES54.UnaryExpression && node.operator === "!" && (sameAccess(node.argument, access) || optionalMemberLengthOf(node.argument, access))) return true;
|
|
12034
|
+
if (node.type !== AST_NODE_TYPES54.BinaryExpression || !["==", "==="].includes(node.operator)) {
|
|
11845
12035
|
return false;
|
|
11846
12036
|
}
|
|
11847
|
-
const nullish = (value) => value.type ===
|
|
12037
|
+
const nullish = (value) => value.type === AST_NODE_TYPES54.Literal && value.value === null || value.type === AST_NODE_TYPES54.Identifier && value.name === "undefined";
|
|
11848
12038
|
return sameAccess(node.left, access) && nullish(node.right) || sameAccess(node.right, access) && nullish(node.left);
|
|
11849
12039
|
}
|
|
11850
12040
|
function isEmptyGuard(node, access) {
|
|
11851
|
-
if (node.type ===
|
|
11852
|
-
if (node.type !==
|
|
12041
|
+
if (node.type === AST_NODE_TYPES54.UnaryExpression && node.operator === "!" && memberLengthOf(node.argument, access)) return true;
|
|
12042
|
+
if (node.type !== AST_NODE_TYPES54.BinaryExpression || !["==", "===", "<="].includes(node.operator)) {
|
|
11853
12043
|
return false;
|
|
11854
12044
|
}
|
|
11855
|
-
const zero = (value) => value.type ===
|
|
12045
|
+
const zero = (value) => value.type === AST_NODE_TYPES54.Literal && value.value === 0;
|
|
11856
12046
|
return memberLengthOf(node.left, access) && zero(node.right) || memberLengthOf(node.right, access) && zero(node.left);
|
|
11857
12047
|
}
|
|
11858
12048
|
function memberLengthOf(node, access) {
|
|
11859
|
-
const target = node.type ===
|
|
11860
|
-
return target.type ===
|
|
12049
|
+
const target = node.type === AST_NODE_TYPES54.ChainExpression ? node.expression : node;
|
|
12050
|
+
return target.type === AST_NODE_TYPES54.MemberExpression && !target.computed && target.property.type === AST_NODE_TYPES54.Identifier && target.property.name === "length" && sameAccess(target.object, access);
|
|
11861
12051
|
}
|
|
11862
12052
|
function optionalMemberLengthOf(node, access) {
|
|
11863
|
-
return node.type ===
|
|
12053
|
+
return node.type === AST_NODE_TYPES54.ChainExpression && node.expression.type === AST_NODE_TYPES54.MemberExpression && node.expression.optional && memberLengthOf(node, access);
|
|
11864
12054
|
}
|
|
11865
12055
|
function hasEquivalentLeadingGuard(fn, access, visitorKeys) {
|
|
11866
|
-
if (fn.body.type !==
|
|
12056
|
+
if (fn.body.type !== AST_NODE_TYPES54.BlockStatement) return false;
|
|
11867
12057
|
const first = fn.body.body[0];
|
|
11868
|
-
if (first?.type !==
|
|
11869
|
-
const terminating = first.consequent.type ===
|
|
12058
|
+
if (first?.type !== AST_NODE_TYPES54.IfStatement) return false;
|
|
12059
|
+
const terminating = first.consequent.type === AST_NODE_TYPES54.ReturnStatement || first.consequent.type === AST_NODE_TYPES54.ThrowStatement || first.consequent.type === AST_NODE_TYPES54.BlockStatement && first.consequent.body.length === 1 && (first.consequent.body[0]?.type === AST_NODE_TYPES54.ReturnStatement || first.consequent.body[0]?.type === AST_NODE_TYPES54.ThrowStatement);
|
|
11870
12060
|
if (!terminating) return false;
|
|
11871
12061
|
if (contains(first.consequent, visitorKeys, (node) => sameAccess(node, access))) return false;
|
|
11872
12062
|
return contains(first.test, visitorKeys, (node) => isNullGuard(node, access)) && contains(first.test, visitorKeys, (node) => isEmptyGuard(node, access));
|
|
@@ -11884,14 +12074,14 @@ function contains(node, visitorKeys, predicate) {
|
|
|
11884
12074
|
function belongsToFunction(node, fn) {
|
|
11885
12075
|
let current = node;
|
|
11886
12076
|
while (current !== void 0 && current !== fn) {
|
|
11887
|
-
if (current !== node && (current.type ===
|
|
12077
|
+
if (current !== node && (current.type === AST_NODE_TYPES54.ArrowFunctionExpression || current.type === AST_NODE_TYPES54.FunctionDeclaration || current.type === AST_NODE_TYPES54.FunctionExpression)) return false;
|
|
11888
12078
|
current = current.parent;
|
|
11889
12079
|
}
|
|
11890
12080
|
return current === fn;
|
|
11891
12081
|
}
|
|
11892
12082
|
function directlyCoalesced(node) {
|
|
11893
12083
|
const parent = node.parent;
|
|
11894
|
-
return parent?.type ===
|
|
12084
|
+
return parent?.type === AST_NODE_TYPES54.LogicalExpression && parent.left === node && (parent.operator === "??" || parent.operator === "||") && emptyArray(parent.right);
|
|
11895
12085
|
}
|
|
11896
12086
|
function identifierIsOnlyCoalesced(context, binding, fn) {
|
|
11897
12087
|
const variable = ASTUtils15.findVariable(context.sourceCode.getScope(binding), binding.name);
|
|
@@ -11906,7 +12096,7 @@ function memberIsOnlyCoalesced(context, object, property, fn) {
|
|
|
11906
12096
|
const accesses = variable.references.flatMap((reference) => {
|
|
11907
12097
|
if (!belongsToFunction(reference.identifier, fn)) return [null];
|
|
11908
12098
|
const parent = reference.identifier.parent;
|
|
11909
|
-
if (parent?.type ===
|
|
12099
|
+
if (parent?.type === AST_NODE_TYPES54.MemberExpression && !parent.computed && parent.object === reference.identifier && parent.property.type === AST_NODE_TYPES54.Identifier && parent.property.name === property) return [parent];
|
|
11910
12100
|
return [];
|
|
11911
12101
|
});
|
|
11912
12102
|
return accesses.length > 0 && accesses.every((access) => access !== null && directlyCoalesced(access));
|
|
@@ -11932,8 +12122,8 @@ var prefer_non_nullable_collection_default = createRule({
|
|
|
11932
12122
|
let shapes = /* @__PURE__ */ new Map();
|
|
11933
12123
|
const evidence = /* @__PURE__ */ new Map();
|
|
11934
12124
|
function propertiesFor(annotation) {
|
|
11935
|
-
if (annotation?.type ===
|
|
11936
|
-
if (annotation?.type ===
|
|
12125
|
+
if (annotation?.type === AST_NODE_TYPES54.TSTypeLiteral) return shapeProperties(annotation.members);
|
|
12126
|
+
if (annotation?.type === AST_NODE_TYPES54.TSTypeReference && annotation.typeName.type === AST_NODE_TYPES54.Identifier) {
|
|
11937
12127
|
const shape = shapes.get(annotation.typeName.name);
|
|
11938
12128
|
return shape?.exported === false ? shape.properties : [];
|
|
11939
12129
|
}
|
|
@@ -11946,21 +12136,21 @@ var prefer_non_nullable_collection_default = createRule({
|
|
|
11946
12136
|
}
|
|
11947
12137
|
function checkFunction(fn) {
|
|
11948
12138
|
for (const rawParameter of fn.params) {
|
|
11949
|
-
const parameter = rawParameter.type ===
|
|
11950
|
-
if (parameter.type ===
|
|
12139
|
+
const parameter = rawParameter.type === AST_NODE_TYPES54.AssignmentPattern ? rawParameter.left : rawParameter;
|
|
12140
|
+
if (parameter.type === AST_NODE_TYPES54.ObjectPattern) {
|
|
11951
12141
|
const properties2 = propertiesFor(parameter.typeAnnotation?.typeAnnotation);
|
|
11952
12142
|
for (const property of properties2) {
|
|
11953
12143
|
const bindingProperty = parameter.properties.find(
|
|
11954
|
-
(entry) => entry.type ===
|
|
12144
|
+
(entry) => entry.type === AST_NODE_TYPES54.Property && !entry.computed && entry.key.type === AST_NODE_TYPES54.Identifier && entry.key.name === property.name
|
|
11955
12145
|
);
|
|
11956
12146
|
if (bindingProperty === void 0) continue;
|
|
11957
12147
|
const value = bindingProperty.value;
|
|
11958
|
-
const binding = value.type ===
|
|
11959
|
-
if (binding.type !==
|
|
12148
|
+
const binding = value.type === AST_NODE_TYPES54.AssignmentPattern ? value.left : value;
|
|
12149
|
+
if (binding.type !== AST_NODE_TYPES54.Identifier) {
|
|
11960
12150
|
record(property, false);
|
|
11961
12151
|
continue;
|
|
11962
12152
|
}
|
|
11963
|
-
if (value.type ===
|
|
12153
|
+
if (value.type === AST_NODE_TYPES54.AssignmentPattern && emptyArray(value.right) && property.acceptsUndefined && !property.acceptsNull) {
|
|
11964
12154
|
record(property, true);
|
|
11965
12155
|
continue;
|
|
11966
12156
|
}
|
|
@@ -11972,7 +12162,7 @@ var prefer_non_nullable_collection_default = createRule({
|
|
|
11972
12162
|
}
|
|
11973
12163
|
continue;
|
|
11974
12164
|
}
|
|
11975
|
-
if (parameter.type !==
|
|
12165
|
+
if (parameter.type !== AST_NODE_TYPES54.Identifier) continue;
|
|
11976
12166
|
const properties = propertiesFor(parameter.typeAnnotation?.typeAnnotation);
|
|
11977
12167
|
for (const property of properties) {
|
|
11978
12168
|
const access = {
|
|
@@ -12010,7 +12200,7 @@ var prefer_non_nullable_collection_default = createRule({
|
|
|
12010
12200
|
|
|
12011
12201
|
// src/rules/prefer-nullish-filter-predicate.ts
|
|
12012
12202
|
import {
|
|
12013
|
-
AST_NODE_TYPES as
|
|
12203
|
+
AST_NODE_TYPES as AST_NODE_TYPES55,
|
|
12014
12204
|
ASTUtils as ASTUtils16,
|
|
12015
12205
|
ESLintUtils as ESLintUtils5
|
|
12016
12206
|
} from "@typescript-eslint/utils";
|
|
@@ -12147,7 +12337,7 @@ var prefer_nullish_filter_predicate_default = createRule({
|
|
|
12147
12337
|
CallExpression(node) {
|
|
12148
12338
|
const callee = node.callee;
|
|
12149
12339
|
const callback = node.arguments[0];
|
|
12150
|
-
if (node.arguments.length !== 1 || callback?.type !==
|
|
12340
|
+
if (node.arguments.length !== 1 || callback?.type !== AST_NODE_TYPES55.Identifier || callback.name !== "Boolean" || callee.type !== AST_NODE_TYPES55.MemberExpression || callee.computed || callee.property.type !== AST_NODE_TYPES55.Identifier || callee.property.name !== "filter" || !isUnshadowedBoolean(callback, context) || !isBuiltinArrayFilter(callee, services)) return;
|
|
12151
12341
|
const elementType = arrayElementType(callee.object, services);
|
|
12152
12342
|
const checker = services.program.getTypeChecker();
|
|
12153
12343
|
if (elementType === null || !isNullishPlusTruthy(elementType, checker)) return;
|
|
@@ -12172,7 +12362,7 @@ var prefer_nullish_filter_predicate_default = createRule({
|
|
|
12172
12362
|
import {
|
|
12173
12363
|
ASTUtils as ASTUtils17,
|
|
12174
12364
|
ESLintUtils as ESLintUtils6,
|
|
12175
|
-
AST_NODE_TYPES as
|
|
12365
|
+
AST_NODE_TYPES as AST_NODE_TYPES56
|
|
12176
12366
|
} from "@typescript-eslint/utils";
|
|
12177
12367
|
import * as ts4 from "typescript";
|
|
12178
12368
|
var PREFER_AWAIT_IN_ASYNC_RETURN_DOCUMENTATION = {
|
|
@@ -12215,10 +12405,10 @@ var PREFER_AWAIT_IN_ASYNC_RETURN_DOCUMENTATION = {
|
|
|
12215
12405
|
};
|
|
12216
12406
|
function directAsyncReturnOwner(node) {
|
|
12217
12407
|
const parent = node.parent;
|
|
12218
|
-
if (parent.type ===
|
|
12408
|
+
if (parent.type === AST_NODE_TYPES56.ArrowFunctionExpression && parent.body === node) {
|
|
12219
12409
|
return parent.async && !parent.generator ? parent : null;
|
|
12220
12410
|
}
|
|
12221
|
-
if (parent.type !==
|
|
12411
|
+
if (parent.type !== AST_NODE_TYPES56.ReturnStatement || parent.argument !== node) {
|
|
12222
12412
|
return null;
|
|
12223
12413
|
}
|
|
12224
12414
|
let owner = parent.parent;
|
|
@@ -12228,15 +12418,15 @@ function directAsyncReturnOwner(node) {
|
|
|
12228
12418
|
return owner !== void 0 && owner.async && !owner.generator ? owner : null;
|
|
12229
12419
|
}
|
|
12230
12420
|
function isRuntimeFunction(node) {
|
|
12231
|
-
return node.type ===
|
|
12421
|
+
return node.type === AST_NODE_TYPES56.ArrowFunctionExpression || node.type === AST_NODE_TYPES56.FunctionDeclaration || node.type === AST_NODE_TYPES56.FunctionExpression;
|
|
12232
12422
|
}
|
|
12233
12423
|
function promiseThenReceiver(node) {
|
|
12234
12424
|
const callee = node.callee;
|
|
12235
|
-
if (callee.type !==
|
|
12425
|
+
if (callee.type !== AST_NODE_TYPES56.MemberExpression || callee.computed || callee.optional || callee.property.type !== AST_NODE_TYPES56.Identifier || callee.property.name !== "then" || node.optional || node.arguments.length !== 1) {
|
|
12236
12426
|
return null;
|
|
12237
12427
|
}
|
|
12238
12428
|
const callback = node.arguments[0];
|
|
12239
|
-
if (callback === void 0 || callback.type !==
|
|
12429
|
+
if (callback === void 0 || callback.type !== AST_NODE_TYPES56.ArrowFunctionExpression && callback.type !== AST_NODE_TYPES56.FunctionExpression) {
|
|
12240
12430
|
return null;
|
|
12241
12431
|
}
|
|
12242
12432
|
return callee.object;
|
|
@@ -12289,7 +12479,7 @@ var prefer_await_in_async_return_default = createRule({
|
|
|
12289
12479
|
};
|
|
12290
12480
|
const isFrameworkLoaderCallback = (owner) => {
|
|
12291
12481
|
const parent = owner.parent;
|
|
12292
|
-
if (parent.type !==
|
|
12482
|
+
if (parent.type !== AST_NODE_TYPES56.CallExpression || parent.arguments[0] !== owner || parent.callee.type !== AST_NODE_TYPES56.Identifier) return false;
|
|
12293
12483
|
const variable = ASTUtils17.findVariable(context.sourceCode.getScope(parent.callee), parent.callee.name);
|
|
12294
12484
|
return variable !== null && frameworkLoaders.has(variable);
|
|
12295
12485
|
};
|
|
@@ -12297,12 +12487,12 @@ var prefer_await_in_async_return_default = createRule({
|
|
|
12297
12487
|
ImportDeclaration(node) {
|
|
12298
12488
|
if (node.source.value === "react") {
|
|
12299
12489
|
for (const specifier of node.specifiers) {
|
|
12300
|
-
if (specifier.type ===
|
|
12490
|
+
if (specifier.type === AST_NODE_TYPES56.ImportSpecifier && (specifier.imported.type === AST_NODE_TYPES56.Identifier ? specifier.imported.name : specifier.imported.value) === "lazy") rememberFrameworkLoader(specifier.local);
|
|
12301
12491
|
}
|
|
12302
12492
|
}
|
|
12303
12493
|
if (node.source.value === "next/dynamic") {
|
|
12304
12494
|
for (const specifier of node.specifiers) {
|
|
12305
|
-
if (specifier.type ===
|
|
12495
|
+
if (specifier.type === AST_NODE_TYPES56.ImportDefaultSpecifier) rememberFrameworkLoader(specifier.local);
|
|
12306
12496
|
}
|
|
12307
12497
|
}
|
|
12308
12498
|
},
|
|
@@ -12320,7 +12510,7 @@ var prefer_await_in_async_return_default = createRule({
|
|
|
12320
12510
|
});
|
|
12321
12511
|
|
|
12322
12512
|
// src/rules/prefer-schema-for-api-payload.ts
|
|
12323
|
-
import { AST_NODE_TYPES as
|
|
12513
|
+
import { AST_NODE_TYPES as AST_NODE_TYPES57 } from "@typescript-eslint/utils";
|
|
12324
12514
|
var PREFER_SCHEMA_FOR_API_PAYLOAD_DOCUMENTATION = {
|
|
12325
12515
|
summary: "Require Zod (or similar) schema validation on `response.json()` / `JSON.parse()` results before property access.",
|
|
12326
12516
|
rationale: "External JSON is untrusted at runtime even when its expected TypeScript shape is known statically.",
|
|
@@ -12332,12 +12522,12 @@ var PREFER_SCHEMA_FOR_API_PAYLOAD_DOCUMENTATION = {
|
|
|
12332
12522
|
{ id: "unvalidated-payload", title: "Do not trust response JSON directly", outcome: "match", files: [{ path: "src/client.ts", source: "async function load(response) { const body = await response.json(); return body.id; }" }], focusPath: "src/client.ts", expectedCount: 1, public: true }
|
|
12333
12523
|
]
|
|
12334
12524
|
};
|
|
12335
|
-
var
|
|
12525
|
+
var unwrap5 = (node) => {
|
|
12336
12526
|
let current = node;
|
|
12337
12527
|
while (current !== null && current !== void 0) {
|
|
12338
|
-
if (current.type ===
|
|
12528
|
+
if (current.type === AST_NODE_TYPES57.TSAsExpression || current.type === AST_NODE_TYPES57.TSTypeAssertion || current.type === AST_NODE_TYPES57.TSNonNullExpression || current.type === AST_NODE_TYPES57.TSSatisfiesExpression) {
|
|
12339
12529
|
current = current.expression;
|
|
12340
|
-
} else if (current.type ===
|
|
12530
|
+
} else if (current.type === AST_NODE_TYPES57.ChainExpression) {
|
|
12341
12531
|
current = current.expression;
|
|
12342
12532
|
} else {
|
|
12343
12533
|
break;
|
|
@@ -12351,24 +12541,24 @@ var PROMISE_CHAIN_METHODS = /* @__PURE__ */ new Set([
|
|
|
12351
12541
|
"finally"
|
|
12352
12542
|
]);
|
|
12353
12543
|
var isSchemaParseReference = (node) => {
|
|
12354
|
-
const inner =
|
|
12355
|
-
return inner !== null && inner.type ===
|
|
12544
|
+
const inner = unwrap5(node);
|
|
12545
|
+
return inner !== null && inner.type === AST_NODE_TYPES57.MemberExpression && !inner.computed && inner.property.type === AST_NODE_TYPES57.Identifier && (inner.property.name === "parse" || inner.property.name === "safeParse");
|
|
12356
12546
|
};
|
|
12357
12547
|
var isRawPayloadSource = (node, isKnownLocalText) => {
|
|
12358
|
-
let current =
|
|
12548
|
+
let current = unwrap5(node);
|
|
12359
12549
|
if (current === null) return false;
|
|
12360
|
-
if (current.type ===
|
|
12361
|
-
current =
|
|
12550
|
+
if (current.type === AST_NODE_TYPES57.AwaitExpression) {
|
|
12551
|
+
current = unwrap5(current.argument);
|
|
12362
12552
|
}
|
|
12363
|
-
if (current === null || current.type !==
|
|
12553
|
+
if (current === null || current.type !== AST_NODE_TYPES57.CallExpression) {
|
|
12364
12554
|
return false;
|
|
12365
12555
|
}
|
|
12366
|
-
const callee =
|
|
12367
|
-
if (callee === null || callee.type !==
|
|
12556
|
+
const callee = unwrap5(current.callee);
|
|
12557
|
+
if (callee === null || callee.type !== AST_NODE_TYPES57.MemberExpression) {
|
|
12368
12558
|
return false;
|
|
12369
12559
|
}
|
|
12370
|
-
const property =
|
|
12371
|
-
if (property === null || property.type !==
|
|
12560
|
+
const property = unwrap5(callee.property);
|
|
12561
|
+
if (property === null || property.type !== AST_NODE_TYPES57.Identifier) {
|
|
12372
12562
|
return false;
|
|
12373
12563
|
}
|
|
12374
12564
|
if (property.name === "json") {
|
|
@@ -12377,18 +12567,18 @@ var isRawPayloadSource = (node, isKnownLocalText) => {
|
|
|
12377
12567
|
if (PROMISE_CHAIN_METHODS.has(property.name)) {
|
|
12378
12568
|
return !current.arguments.some(isSchemaParseReference) && isRawPayloadSource(callee.object);
|
|
12379
12569
|
}
|
|
12380
|
-
const object =
|
|
12381
|
-
return property.name === "parse" && object !== null && object.type ===
|
|
12570
|
+
const object = unwrap5(callee.object);
|
|
12571
|
+
return property.name === "parse" && object !== null && object.type === AST_NODE_TYPES57.Identifier && object.name === "JSON" && !isLocalFileRead(current.arguments[0]) && isKnownLocalText?.(current.arguments[0]) !== true;
|
|
12382
12572
|
};
|
|
12383
12573
|
var FILE_READ_RE = /^(readFile|readFileSync|readJson|readJsonSync|readJSON)$/;
|
|
12384
12574
|
var isDirectLocalFileRead = (node) => {
|
|
12385
|
-
let current =
|
|
12386
|
-
if (current?.type ===
|
|
12387
|
-
current =
|
|
12575
|
+
let current = unwrap5(node);
|
|
12576
|
+
if (current?.type === AST_NODE_TYPES57.AwaitExpression) {
|
|
12577
|
+
current = unwrap5(current.argument);
|
|
12388
12578
|
}
|
|
12389
|
-
if (current?.type !==
|
|
12390
|
-
const callee =
|
|
12391
|
-
const name = callee?.type ===
|
|
12579
|
+
if (current?.type !== AST_NODE_TYPES57.CallExpression) return false;
|
|
12580
|
+
const callee = unwrap5(current.callee);
|
|
12581
|
+
const name = callee?.type === AST_NODE_TYPES57.Identifier ? callee.name : callee?.type === AST_NODE_TYPES57.MemberExpression && !callee.computed && callee.property.type === AST_NODE_TYPES57.Identifier ? callee.property.name : null;
|
|
12392
12582
|
return name !== null && FILE_READ_RE.test(name);
|
|
12393
12583
|
};
|
|
12394
12584
|
var isLocalFileRead = (node) => {
|
|
@@ -12415,15 +12605,15 @@ var isLocalFileRead = (node) => {
|
|
|
12415
12605
|
var ASSERTION_CALLEE_RE = /^(expect|assert|should|invariant)$/;
|
|
12416
12606
|
var isInsideAssertion = (node) => {
|
|
12417
12607
|
for (let current = node.parent; current !== void 0 && current !== null; current = current.parent) {
|
|
12418
|
-
if (current.type !==
|
|
12608
|
+
if (current.type !== AST_NODE_TYPES57.CallExpression) continue;
|
|
12419
12609
|
let callee = current.callee;
|
|
12420
|
-
while (callee.type ===
|
|
12610
|
+
while (callee.type === AST_NODE_TYPES57.MemberExpression) {
|
|
12421
12611
|
callee = callee.object;
|
|
12422
12612
|
}
|
|
12423
|
-
if (callee.type ===
|
|
12613
|
+
if (callee.type === AST_NODE_TYPES57.CallExpression) {
|
|
12424
12614
|
callee = callee.callee;
|
|
12425
12615
|
}
|
|
12426
|
-
if (callee.type ===
|
|
12616
|
+
if (callee.type === AST_NODE_TYPES57.Identifier && ASSERTION_CALLEE_RE.test(callee.name)) {
|
|
12427
12617
|
return true;
|
|
12428
12618
|
}
|
|
12429
12619
|
}
|
|
@@ -12442,22 +12632,22 @@ var GUARD_NAME_RE = /^(?:is|validate|parse|assert|decode|coerce)[A-Z]/;
|
|
|
12442
12632
|
var isValidationRead = (node) => {
|
|
12443
12633
|
let current = node;
|
|
12444
12634
|
let parent = current.parent;
|
|
12445
|
-
while (parent !== null && parent !== void 0 && (parent.type ===
|
|
12635
|
+
while (parent !== null && parent !== void 0 && (parent.type === AST_NODE_TYPES57.TSAsExpression || parent.type === AST_NODE_TYPES57.TSTypeAssertion || parent.type === AST_NODE_TYPES57.TSNonNullExpression || parent.type === AST_NODE_TYPES57.TSSatisfiesExpression || parent.type === AST_NODE_TYPES57.ChainExpression)) {
|
|
12446
12636
|
current = parent;
|
|
12447
12637
|
parent = parent.parent;
|
|
12448
12638
|
}
|
|
12449
12639
|
if (parent === null || parent === void 0) return false;
|
|
12450
|
-
if (parent.type ===
|
|
12640
|
+
if (parent.type === AST_NODE_TYPES57.UnaryExpression && parent.operator === "typeof" && parent.argument === current) {
|
|
12451
12641
|
return true;
|
|
12452
12642
|
}
|
|
12453
|
-
if (parent.type !==
|
|
12643
|
+
if (parent.type !== AST_NODE_TYPES57.CallExpression || !parent.arguments.some((arg) => arg === current)) {
|
|
12454
12644
|
return false;
|
|
12455
12645
|
}
|
|
12456
12646
|
const callee = parent.callee;
|
|
12457
|
-
if (callee.type ===
|
|
12647
|
+
if (callee.type === AST_NODE_TYPES57.MemberExpression && !callee.computed && callee.object.type === AST_NODE_TYPES57.Identifier && callee.object.name === "Array" && callee.property.type === AST_NODE_TYPES57.Identifier && callee.property.name === "isArray") {
|
|
12458
12648
|
return parent.arguments.length === 1;
|
|
12459
12649
|
}
|
|
12460
|
-
return callee.type ===
|
|
12650
|
+
return callee.type === AST_NODE_TYPES57.Identifier && GUARD_NAME_RE.test(callee.name);
|
|
12461
12651
|
};
|
|
12462
12652
|
var PRIMITIVE_TYPEOF_RESULTS = /* @__PURE__ */ new Set([
|
|
12463
12653
|
"bigint",
|
|
@@ -12468,13 +12658,13 @@ var PRIMITIVE_TYPEOF_RESULTS = /* @__PURE__ */ new Set([
|
|
|
12468
12658
|
"undefined"
|
|
12469
12659
|
]);
|
|
12470
12660
|
var bindingValidationPolarity = (test, bindingName) => {
|
|
12471
|
-
if (test.type ===
|
|
12661
|
+
if (test.type === AST_NODE_TYPES57.UnaryExpression && test.operator === "!") {
|
|
12472
12662
|
const inner = bindingValidationPolarity(test.argument, bindingName);
|
|
12473
12663
|
return inner === "valid-when-true" ? "valid-when-false" : inner === "valid-when-false" ? "valid-when-true" : null;
|
|
12474
12664
|
}
|
|
12475
|
-
if (test.type ===
|
|
12476
|
-
const typeofName = (node) => node.type ===
|
|
12477
|
-
const literalType = (node) => node.type ===
|
|
12665
|
+
if (test.type === AST_NODE_TYPES57.BinaryExpression) {
|
|
12666
|
+
const typeofName = (node) => node.type === AST_NODE_TYPES57.UnaryExpression && node.operator === "typeof" && node.argument.type === AST_NODE_TYPES57.Identifier ? node.argument.name : null;
|
|
12667
|
+
const literalType = (node) => node.type === AST_NODE_TYPES57.Literal && typeof node.value === "string" && PRIMITIVE_TYPEOF_RESULTS.has(node.value) ? node.value : null;
|
|
12478
12668
|
const matches = typeofName(test.left) === bindingName && literalType(test.right) !== null || typeofName(test.right) === bindingName && literalType(test.left) !== null;
|
|
12479
12669
|
if (!matches) return null;
|
|
12480
12670
|
if (test.operator === "===" || test.operator === "==") {
|
|
@@ -12482,9 +12672,9 @@ var bindingValidationPolarity = (test, bindingName) => {
|
|
|
12482
12672
|
}
|
|
12483
12673
|
return test.operator === "!==" || test.operator === "!=" ? "valid-when-false" : null;
|
|
12484
12674
|
}
|
|
12485
|
-
return test.type ===
|
|
12675
|
+
return test.type === AST_NODE_TYPES57.CallExpression && test.arguments.length === 1 && test.arguments[0]?.type === AST_NODE_TYPES57.Identifier && test.arguments[0].name === bindingName && test.callee.type === AST_NODE_TYPES57.MemberExpression && !test.callee.computed && test.callee.object.type === AST_NODE_TYPES57.Identifier && test.callee.object.name === "Array" && test.callee.property.type === AST_NODE_TYPES57.Identifier && test.callee.property.name === "isArray" ? "valid-when-true" : null;
|
|
12486
12676
|
};
|
|
12487
|
-
var plainMemberAccess = (node) => node.type ===
|
|
12677
|
+
var plainMemberAccess = (node) => node.type === AST_NODE_TYPES57.MemberExpression && !node.computed && node.object.type === AST_NODE_TYPES57.Identifier && node.property.type === AST_NODE_TYPES57.Identifier ? { object: node.object.name, property: node.property.name } : null;
|
|
12488
12678
|
var isSamePlainMember = (node, access) => {
|
|
12489
12679
|
const candidate2 = plainMemberAccess(node);
|
|
12490
12680
|
return candidate2 !== null && candidate2.object === access.object && candidate2.property === access.property;
|
|
@@ -12492,19 +12682,19 @@ var isSamePlainMember = (node, access) => {
|
|
|
12492
12682
|
var nodeWithin2 = (node, container) => node.range[0] >= container.range[0] && node.range[1] <= container.range[1];
|
|
12493
12683
|
var isUseWithinValidatedBranch = (node, bindingName) => {
|
|
12494
12684
|
for (let current = node.parent; current !== void 0 && current !== null; current = current.parent) {
|
|
12495
|
-
if (current.type ===
|
|
12685
|
+
if (current.type === AST_NODE_TYPES57.ConditionalExpression) {
|
|
12496
12686
|
const polarity = bindingValidationPolarity(current.test, bindingName);
|
|
12497
12687
|
if (polarity === "valid-when-true" && nodeWithin2(node, current.consequent) || polarity === "valid-when-false" && nodeWithin2(node, current.alternate)) {
|
|
12498
12688
|
return true;
|
|
12499
12689
|
}
|
|
12500
12690
|
}
|
|
12501
|
-
if (current.type ===
|
|
12691
|
+
if (current.type === AST_NODE_TYPES57.IfStatement) {
|
|
12502
12692
|
const polarity = bindingValidationPolarity(current.test, bindingName);
|
|
12503
12693
|
if (polarity === "valid-when-true" && nodeWithin2(node, current.consequent) || polarity === "valid-when-false" && current.alternate !== null && nodeWithin2(node, current.alternate)) {
|
|
12504
12694
|
return true;
|
|
12505
12695
|
}
|
|
12506
12696
|
}
|
|
12507
|
-
if (current.type ===
|
|
12697
|
+
if (current.type === AST_NODE_TYPES57.FunctionDeclaration || current.type === AST_NODE_TYPES57.FunctionExpression || current.type === AST_NODE_TYPES57.ArrowFunctionExpression) {
|
|
12508
12698
|
return false;
|
|
12509
12699
|
}
|
|
12510
12700
|
}
|
|
@@ -12512,32 +12702,32 @@ var isUseWithinValidatedBranch = (node, bindingName) => {
|
|
|
12512
12702
|
};
|
|
12513
12703
|
var isMemberUseWithinValidatedBranch = (node, access) => {
|
|
12514
12704
|
for (let current = node.parent; current !== void 0 && current !== null; current = current.parent) {
|
|
12515
|
-
if (current.type ===
|
|
12705
|
+
if (current.type === AST_NODE_TYPES57.ConditionalExpression) {
|
|
12516
12706
|
const polarity = memberValidationPolarity(current.test, access);
|
|
12517
12707
|
if (polarity === "valid-when-true" && nodeWithin2(node, current.consequent) || polarity === "valid-when-false" && nodeWithin2(node, current.alternate)) {
|
|
12518
12708
|
return true;
|
|
12519
12709
|
}
|
|
12520
12710
|
}
|
|
12521
|
-
if (current.type ===
|
|
12711
|
+
if (current.type === AST_NODE_TYPES57.IfStatement) {
|
|
12522
12712
|
const polarity = memberValidationPolarity(current.test, access);
|
|
12523
12713
|
if (polarity === "valid-when-true" && nodeWithin2(node, current.consequent) || polarity === "valid-when-false" && current.alternate !== null && nodeWithin2(node, current.alternate)) {
|
|
12524
12714
|
return true;
|
|
12525
12715
|
}
|
|
12526
12716
|
}
|
|
12527
|
-
if (current.type ===
|
|
12717
|
+
if (current.type === AST_NODE_TYPES57.FunctionDeclaration || current.type === AST_NODE_TYPES57.FunctionExpression || current.type === AST_NODE_TYPES57.ArrowFunctionExpression) {
|
|
12528
12718
|
return false;
|
|
12529
12719
|
}
|
|
12530
12720
|
}
|
|
12531
12721
|
return false;
|
|
12532
12722
|
};
|
|
12533
12723
|
var memberValidationPolarity = (test, access) => {
|
|
12534
|
-
if (test.type ===
|
|
12724
|
+
if (test.type === AST_NODE_TYPES57.UnaryExpression && test.operator === "!") {
|
|
12535
12725
|
const inner = memberValidationPolarity(test.argument, access);
|
|
12536
12726
|
return inner === "valid-when-true" ? "valid-when-false" : inner === "valid-when-false" ? "valid-when-true" : null;
|
|
12537
12727
|
}
|
|
12538
|
-
if (test.type ===
|
|
12539
|
-
const isMatchingTypeof = (node) => node.type ===
|
|
12540
|
-
const isPrimitiveType = (node) => node.type ===
|
|
12728
|
+
if (test.type === AST_NODE_TYPES57.BinaryExpression) {
|
|
12729
|
+
const isMatchingTypeof = (node) => node.type === AST_NODE_TYPES57.UnaryExpression && node.operator === "typeof" && isSamePlainMember(node.argument, access);
|
|
12730
|
+
const isPrimitiveType = (node) => node.type === AST_NODE_TYPES57.Literal && typeof node.value === "string" && PRIMITIVE_TYPEOF_RESULTS.has(node.value);
|
|
12541
12731
|
if (!(isMatchingTypeof(test.left) && isPrimitiveType(test.right) || isMatchingTypeof(test.right) && isPrimitiveType(test.left))) {
|
|
12542
12732
|
return null;
|
|
12543
12733
|
}
|
|
@@ -12546,15 +12736,15 @@ var memberValidationPolarity = (test, access) => {
|
|
|
12546
12736
|
}
|
|
12547
12737
|
return test.operator === "!==" || test.operator === "!=" ? "valid-when-false" : null;
|
|
12548
12738
|
}
|
|
12549
|
-
return test.type ===
|
|
12739
|
+
return test.type === AST_NODE_TYPES57.CallExpression && test.arguments.length === 1 && test.arguments[0] !== void 0 && test.arguments[0].type !== AST_NODE_TYPES57.SpreadElement && isSamePlainMember(test.arguments[0], access) && test.callee.type === AST_NODE_TYPES57.MemberExpression && !test.callee.computed && test.callee.object.type === AST_NODE_TYPES57.Identifier && test.callee.object.name === "Array" && test.callee.property.type === AST_NODE_TYPES57.Identifier && test.callee.property.name === "isArray" ? "valid-when-true" : null;
|
|
12550
12740
|
};
|
|
12551
12741
|
var isFullyValidatedExtractedBinding = (member, source, context) => {
|
|
12552
12742
|
const isValidationReference = (identifier) => {
|
|
12553
12743
|
for (let current = identifier.parent; current !== void 0 && current !== null; current = current.parent) {
|
|
12554
|
-
if ((current.type ===
|
|
12744
|
+
if ((current.type === AST_NODE_TYPES57.BinaryExpression || current.type === AST_NODE_TYPES57.CallExpression || current.type === AST_NODE_TYPES57.UnaryExpression) && bindingValidationPolarity(current, identifier.name) !== null) {
|
|
12555
12745
|
return true;
|
|
12556
12746
|
}
|
|
12557
|
-
if (current.type !==
|
|
12747
|
+
if (current.type !== AST_NODE_TYPES57.UnaryExpression && current.type !== AST_NODE_TYPES57.MemberExpression && current.type !== AST_NODE_TYPES57.CallExpression) {
|
|
12558
12748
|
return false;
|
|
12559
12749
|
}
|
|
12560
12750
|
}
|
|
@@ -12562,7 +12752,7 @@ var isFullyValidatedExtractedBinding = (member, source, context) => {
|
|
|
12562
12752
|
};
|
|
12563
12753
|
const isGuardedUse = (identifier) => {
|
|
12564
12754
|
for (let current = identifier.parent; current !== void 0 && current !== null; current = current.parent) {
|
|
12565
|
-
if (current.type ===
|
|
12755
|
+
if (current.type === AST_NODE_TYPES57.ConditionalExpression) {
|
|
12566
12756
|
const polarity = bindingValidationPolarity(current.test, identifier.name);
|
|
12567
12757
|
if (polarity === "valid-when-true" && nodeWithin2(identifier, current.consequent)) {
|
|
12568
12758
|
return true;
|
|
@@ -12571,7 +12761,7 @@ var isFullyValidatedExtractedBinding = (member, source, context) => {
|
|
|
12571
12761
|
return true;
|
|
12572
12762
|
}
|
|
12573
12763
|
}
|
|
12574
|
-
if (current.type ===
|
|
12764
|
+
if (current.type === AST_NODE_TYPES57.IfStatement) {
|
|
12575
12765
|
const polarity = bindingValidationPolarity(current.test, identifier.name);
|
|
12576
12766
|
if (polarity === "valid-when-true" && nodeWithin2(identifier, current.consequent)) {
|
|
12577
12767
|
return true;
|
|
@@ -12580,14 +12770,14 @@ var isFullyValidatedExtractedBinding = (member, source, context) => {
|
|
|
12580
12770
|
return true;
|
|
12581
12771
|
}
|
|
12582
12772
|
}
|
|
12583
|
-
if (current.type ===
|
|
12773
|
+
if (current.type === AST_NODE_TYPES57.FunctionDeclaration || current.type === AST_NODE_TYPES57.FunctionExpression || current.type === AST_NODE_TYPES57.ArrowFunctionExpression) {
|
|
12584
12774
|
return false;
|
|
12585
12775
|
}
|
|
12586
12776
|
}
|
|
12587
12777
|
return false;
|
|
12588
12778
|
};
|
|
12589
12779
|
const declarator = member.parent;
|
|
12590
|
-
if (declarator.type !==
|
|
12780
|
+
if (declarator.type !== AST_NODE_TYPES57.VariableDeclarator || declarator.init !== member || declarator.id.type !== AST_NODE_TYPES57.Identifier || declarator.parent.type !== AST_NODE_TYPES57.VariableDeclaration || declarator.parent.kind !== "const") {
|
|
12591
12781
|
return false;
|
|
12592
12782
|
}
|
|
12593
12783
|
const extracted = context.sourceCode.getDeclaredVariables(declarator)[0];
|
|
@@ -12595,7 +12785,7 @@ var isFullyValidatedExtractedBinding = (member, source, context) => {
|
|
|
12595
12785
|
let hasValueUse = false;
|
|
12596
12786
|
for (const reference of extracted.references) {
|
|
12597
12787
|
const identifier = reference.identifier;
|
|
12598
|
-
if (identifier.type !==
|
|
12788
|
+
if (identifier.type !== AST_NODE_TYPES57.Identifier) return false;
|
|
12599
12789
|
if (nodeWithin2(identifier, declarator)) continue;
|
|
12600
12790
|
if (isValidationReference(identifier)) continue;
|
|
12601
12791
|
hasValueUse = true;
|
|
@@ -12608,17 +12798,17 @@ var isGuardTestPosition = (node) => {
|
|
|
12608
12798
|
let parent = current.parent;
|
|
12609
12799
|
while (parent !== void 0 && parent !== null) {
|
|
12610
12800
|
switch (parent.type) {
|
|
12611
|
-
case
|
|
12612
|
-
case
|
|
12613
|
-
case
|
|
12801
|
+
case AST_NODE_TYPES57.UnaryExpression:
|
|
12802
|
+
case AST_NODE_TYPES57.LogicalExpression:
|
|
12803
|
+
case AST_NODE_TYPES57.ChainExpression:
|
|
12614
12804
|
current = parent;
|
|
12615
12805
|
parent = parent.parent;
|
|
12616
12806
|
continue;
|
|
12617
|
-
case
|
|
12618
|
-
case
|
|
12619
|
-
case
|
|
12620
|
-
case
|
|
12621
|
-
case
|
|
12807
|
+
case AST_NODE_TYPES57.IfStatement:
|
|
12808
|
+
case AST_NODE_TYPES57.ConditionalExpression:
|
|
12809
|
+
case AST_NODE_TYPES57.WhileStatement:
|
|
12810
|
+
case AST_NODE_TYPES57.DoWhileStatement:
|
|
12811
|
+
case AST_NODE_TYPES57.ForStatement:
|
|
12622
12812
|
return parent.test === current;
|
|
12623
12813
|
default:
|
|
12624
12814
|
return false;
|
|
@@ -12627,8 +12817,8 @@ var isGuardTestPosition = (node) => {
|
|
|
12627
12817
|
return false;
|
|
12628
12818
|
};
|
|
12629
12819
|
var unvalidatedVariableRef = (node, scope, tracked) => {
|
|
12630
|
-
const unwrapped =
|
|
12631
|
-
if (unwrapped === null || unwrapped.type !==
|
|
12820
|
+
const unwrapped = unwrap5(node);
|
|
12821
|
+
if (unwrapped === null || unwrapped.type !== AST_NODE_TYPES57.Identifier) {
|
|
12632
12822
|
return null;
|
|
12633
12823
|
}
|
|
12634
12824
|
const variable = findVariable2(scope, unwrapped.name);
|
|
@@ -12656,8 +12846,8 @@ var prefer_schema_for_api_payload_default = createRule({
|
|
|
12656
12846
|
const aliasGroups = /* @__PURE__ */ new Map();
|
|
12657
12847
|
const localFileTextVariables = /* @__PURE__ */ new Set();
|
|
12658
12848
|
const localFileTextRef = (node, scope) => {
|
|
12659
|
-
const unwrapped =
|
|
12660
|
-
if (unwrapped?.type !==
|
|
12849
|
+
const unwrapped = unwrap5(node);
|
|
12850
|
+
if (unwrapped?.type !== AST_NODE_TYPES57.Identifier) return null;
|
|
12661
12851
|
const variable = findVariable2(scope, unwrapped.name);
|
|
12662
12852
|
return variable !== null && localFileTextVariables.has(variable) ? variable : null;
|
|
12663
12853
|
};
|
|
@@ -12726,7 +12916,7 @@ var prefer_schema_for_api_payload_default = createRule({
|
|
|
12726
12916
|
return {
|
|
12727
12917
|
VariableDeclarator(node) {
|
|
12728
12918
|
const scope = context.sourceCode.getScope(node);
|
|
12729
|
-
if (node.id.type ===
|
|
12919
|
+
if (node.id.type === AST_NODE_TYPES57.Identifier) {
|
|
12730
12920
|
const variable = context.sourceCode.getDeclaredVariables(node)[0];
|
|
12731
12921
|
if (variable !== void 0) {
|
|
12732
12922
|
updateLocalFileText(variable, node.init, scope);
|
|
@@ -12734,7 +12924,7 @@ var prefer_schema_for_api_payload_default = createRule({
|
|
|
12734
12924
|
trackInitializer(node, scope);
|
|
12735
12925
|
return;
|
|
12736
12926
|
}
|
|
12737
|
-
if (node.id.type ===
|
|
12927
|
+
if (node.id.type === AST_NODE_TYPES57.ObjectPattern || node.id.type === AST_NODE_TYPES57.ArrayPattern) {
|
|
12738
12928
|
if (isRawPayloadSource(
|
|
12739
12929
|
node.init,
|
|
12740
12930
|
(candidate2) => localFileTextRef(candidate2, scope) !== null
|
|
@@ -12751,7 +12941,7 @@ var prefer_schema_for_api_payload_default = createRule({
|
|
|
12751
12941
|
},
|
|
12752
12942
|
AssignmentExpression(node) {
|
|
12753
12943
|
const scope = context.sourceCode.getScope(node);
|
|
12754
|
-
if (node.left.type ===
|
|
12944
|
+
if (node.left.type === AST_NODE_TYPES57.Identifier) {
|
|
12755
12945
|
const variable = findVariable2(scope, node.left.name);
|
|
12756
12946
|
if (variable === null) return;
|
|
12757
12947
|
const isLocalText = (candidate2) => localFileTextRef(candidate2, scope) !== null;
|
|
@@ -12765,7 +12955,7 @@ var prefer_schema_for_api_payload_default = createRule({
|
|
|
12765
12955
|
}
|
|
12766
12956
|
return;
|
|
12767
12957
|
}
|
|
12768
|
-
if (node.left.type ===
|
|
12958
|
+
if (node.left.type === AST_NODE_TYPES57.ObjectPattern || node.left.type === AST_NODE_TYPES57.ArrayPattern) {
|
|
12769
12959
|
if (isRawPayloadSource(
|
|
12770
12960
|
node.right,
|
|
12771
12961
|
(candidate2) => localFileTextRef(candidate2, scope) !== null
|
|
@@ -12785,15 +12975,15 @@ var prefer_schema_for_api_payload_default = createRule({
|
|
|
12785
12975
|
}
|
|
12786
12976
|
},
|
|
12787
12977
|
CallExpression(node) {
|
|
12788
|
-
if (node.callee.type !==
|
|
12978
|
+
if (node.callee.type !== AST_NODE_TYPES57.Identifier) return;
|
|
12789
12979
|
if (!GUARD_NAME_RE.test(node.callee.name) && !isGuardTestPosition(node)) {
|
|
12790
12980
|
return;
|
|
12791
12981
|
}
|
|
12792
12982
|
const scope = context.sourceCode.getScope(node);
|
|
12793
12983
|
for (const arg of node.arguments) {
|
|
12794
|
-
if (arg.type ===
|
|
12795
|
-
const unwrapped =
|
|
12796
|
-
if (unwrapped === null || unwrapped.type !==
|
|
12984
|
+
if (arg.type === AST_NODE_TYPES57.SpreadElement) continue;
|
|
12985
|
+
const unwrapped = unwrap5(arg);
|
|
12986
|
+
if (unwrapped === null || unwrapped.type !== AST_NODE_TYPES57.Identifier) {
|
|
12797
12987
|
continue;
|
|
12798
12988
|
}
|
|
12799
12989
|
const variable = findVariable2(scope, unwrapped.name);
|
|
@@ -12804,20 +12994,20 @@ var prefer_schema_for_api_payload_default = createRule({
|
|
|
12804
12994
|
if (isInsideAssertion(node)) return;
|
|
12805
12995
|
if (isValidationRead(node)) return;
|
|
12806
12996
|
const scope = context.sourceCode.getScope(node);
|
|
12807
|
-
const obj =
|
|
12997
|
+
const obj = unwrap5(node.object);
|
|
12808
12998
|
if (isRawPayloadSource(
|
|
12809
12999
|
obj,
|
|
12810
13000
|
(candidate2) => localFileTextRef(candidate2, scope) !== null
|
|
12811
13001
|
)) {
|
|
12812
13002
|
const parent = node.parent;
|
|
12813
|
-
if (parent.type ===
|
|
13003
|
+
if (parent.type === AST_NODE_TYPES57.CallExpression && parent.callee === node && node.property.type === AST_NODE_TYPES57.Identifier && (node.property.name === "parse" || node.property.name === "safeParse" || PROMISE_CHAIN_METHODS.has(node.property.name))) {
|
|
12814
13004
|
return;
|
|
12815
13005
|
}
|
|
12816
13006
|
context.report({ node, messageId: "unparsedJsonAccess" });
|
|
12817
13007
|
return;
|
|
12818
13008
|
}
|
|
12819
|
-
const variable = obj?.type ===
|
|
12820
|
-
if (variable !== null && obj?.type ===
|
|
13009
|
+
const variable = obj?.type === AST_NODE_TYPES57.Identifier ? unvalidatedVariableRef(obj, scope, unvalidatedVariables) : null;
|
|
13010
|
+
if (variable !== null && obj?.type === AST_NODE_TYPES57.Identifier) {
|
|
12821
13011
|
if (isUseWithinValidatedBranch(node, obj.name)) {
|
|
12822
13012
|
return;
|
|
12823
13013
|
}
|
|
@@ -12836,8 +13026,122 @@ var prefer_schema_for_api_payload_default = createRule({
|
|
|
12836
13026
|
}
|
|
12837
13027
|
});
|
|
12838
13028
|
|
|
13029
|
+
// src/rules/prefer-shared-zod-enum.ts
|
|
13030
|
+
import { AST_NODE_TYPES as AST_NODE_TYPES58 } from "@typescript-eslint/utils";
|
|
13031
|
+
var PREFER_SHARED_ZOD_ENUM_DOCUMENTATION = {
|
|
13032
|
+
summary: "Reuse identical literal Zod enum domains within a module.",
|
|
13033
|
+
rationale: "Repeating the same literal domain creates parallel contracts that can drift independently.",
|
|
13034
|
+
remediation: "Declare one module-level named Zod enum schema and reuse it at each field or contract site.",
|
|
13035
|
+
category: "maintainability",
|
|
13036
|
+
limitations: ["Only direct z.enum calls with ordered string-literal arrays in the same module are compared."],
|
|
13037
|
+
examples: [
|
|
13038
|
+
{ id: "shared-provider", title: "Reuse a named enum schema", outcome: "no-match", files: [{ path: "src/provider.ts", source: "import { z } from 'zod'; const ProviderSchema = z.enum(['agy', 'claude', 'sol']); const JobSchema = z.object({ provider: ProviderSchema }); const StatusSchema = z.object({ provider: ProviderSchema.optional() });" }], focusPath: "src/provider.ts", expectedCount: 0, public: true },
|
|
13039
|
+
{ id: "duplicate-provider", title: "Do not repeat one enum domain", outcome: "match", files: [{ path: "src/provider.ts", source: "import { z } from 'zod'; const JobSchema = z.object({ provider: z.enum(['agy', 'claude', 'sol']) }); const StatusSchema = z.object({ provider: z.enum(['agy', 'claude', 'sol']).optional() });" }], focusPath: "src/provider.ts", expectedCount: 1, public: true }
|
|
13040
|
+
]
|
|
13041
|
+
};
|
|
13042
|
+
function literalDomain(node) {
|
|
13043
|
+
const [argument] = node.arguments;
|
|
13044
|
+
if (argument?.type !== AST_NODE_TYPES58.ArrayExpression || argument.elements.length < 2) return null;
|
|
13045
|
+
const values = [];
|
|
13046
|
+
for (const element of argument.elements) {
|
|
13047
|
+
if (element?.type !== AST_NODE_TYPES58.Literal || typeof element.value !== "string") return null;
|
|
13048
|
+
values.push(element.value);
|
|
13049
|
+
}
|
|
13050
|
+
return values;
|
|
13051
|
+
}
|
|
13052
|
+
var prefer_shared_zod_enum_default = createRule({
|
|
13053
|
+
name: "prefer-shared-zod-enum",
|
|
13054
|
+
documentation: PREFER_SHARED_ZOD_ENUM_DOCUMENTATION,
|
|
13055
|
+
meta: {
|
|
13056
|
+
type: "suggestion",
|
|
13057
|
+
docs: { description: "Reuse identical literal Zod enum domains within a module." },
|
|
13058
|
+
schema: [],
|
|
13059
|
+
messages: {
|
|
13060
|
+
shareEnumDomain: "This Zod enum repeats an earlier identical domain; extract and reuse one module-level named schema."
|
|
13061
|
+
}
|
|
13062
|
+
},
|
|
13063
|
+
defaultOptions: [],
|
|
13064
|
+
create(context) {
|
|
13065
|
+
if (isTestFile(context.filename) || isGeneratedFile(context.filename, context.sourceCode.text)) return {};
|
|
13066
|
+
const zodBindings = /* @__PURE__ */ new Set();
|
|
13067
|
+
const seen = /* @__PURE__ */ new Set();
|
|
13068
|
+
return {
|
|
13069
|
+
ImportDeclaration(node) {
|
|
13070
|
+
if (!isZodModule(node.source.value)) return;
|
|
13071
|
+
for (const specifier of node.specifiers) {
|
|
13072
|
+
if (specifier.type === AST_NODE_TYPES58.ImportNamespaceSpecifier || specifier.type === AST_NODE_TYPES58.ImportDefaultSpecifier || specifier.type === AST_NODE_TYPES58.ImportSpecifier && specifier.imported.type === AST_NODE_TYPES58.Identifier && specifier.imported.name === "z") zodBindings.add(specifier.local.name);
|
|
13073
|
+
}
|
|
13074
|
+
},
|
|
13075
|
+
CallExpression(node) {
|
|
13076
|
+
if (node.callee.type !== AST_NODE_TYPES58.MemberExpression || node.callee.computed || node.callee.object.type !== AST_NODE_TYPES58.Identifier || !zodBindings.has(node.callee.object.name) || node.callee.property.type !== AST_NODE_TYPES58.Identifier || node.callee.property.name !== "enum") return;
|
|
13077
|
+
const domain = literalDomain(node);
|
|
13078
|
+
if (domain === null) return;
|
|
13079
|
+
const key = JSON.stringify(domain);
|
|
13080
|
+
if (seen.has(key)) context.report({ node, messageId: "shareEnumDomain" });
|
|
13081
|
+
else seen.add(key);
|
|
13082
|
+
}
|
|
13083
|
+
};
|
|
13084
|
+
}
|
|
13085
|
+
});
|
|
13086
|
+
|
|
13087
|
+
// src/rules/prefer-switch-for-repeated-equality.ts
|
|
13088
|
+
import { AST_NODE_TYPES as AST_NODE_TYPES59 } from "@typescript-eslint/utils";
|
|
13089
|
+
var PREFER_SWITCH_FOR_REPEATED_EQUALITY_DOCUMENTATION = {
|
|
13090
|
+
summary: "Prefer switch over long if/else-if chains that compare one value for strict equality.",
|
|
13091
|
+
rationale: "A switch makes finite dispatch cases visually uniform and easier to extend without duplicating the discriminant.",
|
|
13092
|
+
remediation: "Replace three or more strict-equality branches over the same discriminant with a switch; keep if statements for ranges, guards, and heterogeneous predicates.",
|
|
13093
|
+
category: "maintainability",
|
|
13094
|
+
limitations: [
|
|
13095
|
+
"Only direct if/else-if chains with at least three strict-equality tests are reported.",
|
|
13096
|
+
"The rule deliberately ignores compound predicates, loose equality, ranges, and chains that compare different discriminants."
|
|
13097
|
+
],
|
|
13098
|
+
examples: [
|
|
13099
|
+
{ id: "switch-dispatch", title: "Make finite dispatch explicit", outcome: "no-match", files: [{ path: "src/render.ts", source: "switch (kind) { case 'a': return a(); case 'b': return b(); case 'c': return c(); default: return fallback(); }" }], focusPath: "src/render.ts", expectedCount: 0, public: true },
|
|
13100
|
+
{ id: "repeated-equality", title: "Avoid repeating the discriminant", outcome: "match", files: [{ path: "src/render.ts", source: "if (kind === 'a') return a(); else if (kind === 'b') return b(); else if (kind === 'c') return c();" }], focusPath: "src/render.ts", expectedCount: 1, public: true }
|
|
13101
|
+
]
|
|
13102
|
+
};
|
|
13103
|
+
function discriminantText(sourceCode, test) {
|
|
13104
|
+
if (test.type !== AST_NODE_TYPES59.BinaryExpression || test.operator !== "===") return null;
|
|
13105
|
+
const leftIsCase = test.left.type === AST_NODE_TYPES59.Literal;
|
|
13106
|
+
const rightIsCase = test.right.type === AST_NODE_TYPES59.Literal;
|
|
13107
|
+
if (leftIsCase === rightIsCase) return null;
|
|
13108
|
+
return sourceCode.getText(leftIsCase ? test.right : test.left);
|
|
13109
|
+
}
|
|
13110
|
+
var prefer_switch_for_repeated_equality_default = createRule({
|
|
13111
|
+
name: "prefer-switch-for-repeated-equality",
|
|
13112
|
+
documentation: PREFER_SWITCH_FOR_REPEATED_EQUALITY_DOCUMENTATION,
|
|
13113
|
+
meta: {
|
|
13114
|
+
type: "suggestion",
|
|
13115
|
+
docs: { description: "Prefer switch over long if/else-if chains that compare one value for strict equality." },
|
|
13116
|
+
schema: [],
|
|
13117
|
+
messages: {
|
|
13118
|
+
preferSwitch: "This if/else-if chain repeatedly compares `{{discriminant}}`; use a switch for the finite cases."
|
|
13119
|
+
}
|
|
13120
|
+
},
|
|
13121
|
+
defaultOptions: [],
|
|
13122
|
+
create(context) {
|
|
13123
|
+
return {
|
|
13124
|
+
IfStatement(node) {
|
|
13125
|
+
if (node.parent.type === AST_NODE_TYPES59.IfStatement && node.parent.alternate === node) return;
|
|
13126
|
+
const first = discriminantText(context.sourceCode, node.test);
|
|
13127
|
+
if (first === null) return;
|
|
13128
|
+
let count = 1;
|
|
13129
|
+
let current = node.alternate;
|
|
13130
|
+
while (current?.type === AST_NODE_TYPES59.IfStatement) {
|
|
13131
|
+
if (discriminantText(context.sourceCode, current.test) !== first) return;
|
|
13132
|
+
count += 1;
|
|
13133
|
+
current = current.alternate;
|
|
13134
|
+
}
|
|
13135
|
+
if (count >= 3) {
|
|
13136
|
+
context.report({ node, messageId: "preferSwitch", data: { discriminant: first } });
|
|
13137
|
+
}
|
|
13138
|
+
}
|
|
13139
|
+
};
|
|
13140
|
+
}
|
|
13141
|
+
});
|
|
13142
|
+
|
|
12839
13143
|
// src/rules/prefer-semantic-colors.ts
|
|
12840
|
-
import { AST_NODE_TYPES as
|
|
13144
|
+
import { AST_NODE_TYPES as AST_NODE_TYPES60 } from "@typescript-eslint/utils";
|
|
12841
13145
|
import { existsSync, readdirSync, readFileSync } from "fs";
|
|
12842
13146
|
import { dirname, join, parse } from "path";
|
|
12843
13147
|
|
|
@@ -12949,7 +13253,7 @@ var SVG_EXEMPT_COLOR_VALUES = /* @__PURE__ */ new Set([
|
|
|
12949
13253
|
var isInsideSvg = (node) => {
|
|
12950
13254
|
let current = node.parent;
|
|
12951
13255
|
while (current !== void 0 && current !== null) {
|
|
12952
|
-
if (current.type ===
|
|
13256
|
+
if (current.type === AST_NODE_TYPES60.JSXElement) {
|
|
12953
13257
|
const name = jsxElementName(current);
|
|
12954
13258
|
if (name !== null && isSvgLikeElementName(name)) return true;
|
|
12955
13259
|
}
|
|
@@ -12959,8 +13263,8 @@ var isInsideSvg = (node) => {
|
|
|
12959
13263
|
};
|
|
12960
13264
|
function jsxElementName(node) {
|
|
12961
13265
|
const name = node.openingElement.name;
|
|
12962
|
-
if (name.type ===
|
|
12963
|
-
if (name.type ===
|
|
13266
|
+
if (name.type === AST_NODE_TYPES60.JSXIdentifier) return name.name;
|
|
13267
|
+
if (name.type === AST_NODE_TYPES60.JSXMemberExpression && name.property.type === AST_NODE_TYPES60.JSXIdentifier) {
|
|
12964
13268
|
return name.property.name;
|
|
12965
13269
|
}
|
|
12966
13270
|
return null;
|
|
@@ -12986,7 +13290,7 @@ function isSvgLikeElementName(name) {
|
|
|
12986
13290
|
var isInsideIconFactoryPath = (node) => {
|
|
12987
13291
|
let current = node.parent;
|
|
12988
13292
|
while (current !== void 0 && current !== null) {
|
|
12989
|
-
if (current.type ===
|
|
13293
|
+
if (current.type === AST_NODE_TYPES60.Property && propName(current.key) === "path" && current.parent.type === AST_NODE_TYPES60.ObjectExpression && current.parent.parent.type === AST_NODE_TYPES60.CallExpression && current.parent.parent.callee.type === AST_NODE_TYPES60.Identifier && current.parent.parent.callee.name === "createIcon") {
|
|
12990
13294
|
return true;
|
|
12991
13295
|
}
|
|
12992
13296
|
current = current.parent;
|
|
@@ -13120,12 +13424,12 @@ var expandWorkspaceGlob = (root, glob) => {
|
|
|
13120
13424
|
return readdirSync(parent, { withFileTypes: true }).filter((entry) => entry.isDirectory() && !entry.name.startsWith(".")).map((entry) => join(parent, entry.name));
|
|
13121
13425
|
};
|
|
13122
13426
|
var propName = (key) => {
|
|
13123
|
-
if (key.type ===
|
|
13124
|
-
if (key.type ===
|
|
13427
|
+
if (key.type === AST_NODE_TYPES60.Identifier) return key.name;
|
|
13428
|
+
if (key.type === AST_NODE_TYPES60.Literal && typeof key.value === "string") return key.value;
|
|
13125
13429
|
return null;
|
|
13126
13430
|
};
|
|
13127
13431
|
var staticallyImportsEmailOrPdfRenderer = (program) => program.body.some((statement) => {
|
|
13128
|
-
if (statement.type !==
|
|
13432
|
+
if (statement.type !== AST_NODE_TYPES60.ImportDeclaration && statement.type !== AST_NODE_TYPES60.ExportNamedDeclaration && statement.type !== AST_NODE_TYPES60.ExportAllDeclaration) {
|
|
13129
13433
|
return false;
|
|
13130
13434
|
}
|
|
13131
13435
|
return statement.source !== null && typeof statement.source.value === "string" && EMAIL_OR_PDF_MODULE_RE.test(statement.source.value);
|
|
@@ -13162,43 +13466,43 @@ var prefer_semantic_colors_default = createRule({
|
|
|
13162
13466
|
}
|
|
13163
13467
|
let importsEmailOrPdfRenderer = false;
|
|
13164
13468
|
const pendingReports = [];
|
|
13165
|
-
const
|
|
13469
|
+
const report2 = (node, messageId, data) => {
|
|
13166
13470
|
pendingReports.push({ node, messageId, data });
|
|
13167
13471
|
};
|
|
13168
13472
|
const reportClasses = (value, node) => {
|
|
13169
13473
|
for (const token of classTokens(value)) {
|
|
13170
13474
|
const base = tailwindBase(token);
|
|
13171
13475
|
if (RAW_PALETTE_RE.test(base)) {
|
|
13172
|
-
|
|
13476
|
+
report2(node, "rawPalette", { class: token });
|
|
13173
13477
|
} else if (ARBITRARY_COLOR_RE.test(base) && !CSS_VAR_REFERENCE_RE.test(base)) {
|
|
13174
|
-
|
|
13478
|
+
report2(node, "arbitraryColor", { class: token });
|
|
13175
13479
|
}
|
|
13176
13480
|
}
|
|
13177
13481
|
};
|
|
13178
13482
|
const checkClassNode = (node) => {
|
|
13179
13483
|
if (node === null) return;
|
|
13180
13484
|
switch (node.type) {
|
|
13181
|
-
case
|
|
13485
|
+
case AST_NODE_TYPES60.Literal:
|
|
13182
13486
|
if (typeof node.value === "string") reportClasses(node.value, node);
|
|
13183
13487
|
break;
|
|
13184
|
-
case
|
|
13488
|
+
case AST_NODE_TYPES60.TemplateLiteral:
|
|
13185
13489
|
for (const quasi of node.quasis) reportClasses(quasi.value.cooked ?? "", quasi);
|
|
13186
13490
|
break;
|
|
13187
|
-
case
|
|
13491
|
+
case AST_NODE_TYPES60.ArrayExpression:
|
|
13188
13492
|
for (const element of node.elements) {
|
|
13189
|
-
if (element !== null && element.type !==
|
|
13493
|
+
if (element !== null && element.type !== AST_NODE_TYPES60.SpreadElement) checkClassNode(element);
|
|
13190
13494
|
}
|
|
13191
13495
|
break;
|
|
13192
|
-
case
|
|
13496
|
+
case AST_NODE_TYPES60.ObjectExpression:
|
|
13193
13497
|
for (const property of node.properties) {
|
|
13194
|
-
if (property.type ===
|
|
13498
|
+
if (property.type === AST_NODE_TYPES60.Property) checkClassNode(property.value);
|
|
13195
13499
|
}
|
|
13196
13500
|
break;
|
|
13197
|
-
case
|
|
13501
|
+
case AST_NODE_TYPES60.ConditionalExpression:
|
|
13198
13502
|
checkClassNode(node.consequent);
|
|
13199
13503
|
checkClassNode(node.alternate);
|
|
13200
13504
|
break;
|
|
13201
|
-
case
|
|
13505
|
+
case AST_NODE_TYPES60.LogicalExpression:
|
|
13202
13506
|
checkClassNode(node.right);
|
|
13203
13507
|
break;
|
|
13204
13508
|
default:
|
|
@@ -13206,32 +13510,32 @@ var prefer_semantic_colors_default = createRule({
|
|
|
13206
13510
|
}
|
|
13207
13511
|
};
|
|
13208
13512
|
const checkColorValueNode = (node) => {
|
|
13209
|
-
if (node.type ===
|
|
13210
|
-
|
|
13513
|
+
if (node.type === AST_NODE_TYPES60.Literal && typeof node.value === "string" && RAW_COLOR_VALUE_RE.test(node.value) && !CSS_VAR_REFERENCE_RE.test(node.value)) {
|
|
13514
|
+
report2(node, "inlineColor", { value: node.value });
|
|
13211
13515
|
}
|
|
13212
13516
|
};
|
|
13213
13517
|
return {
|
|
13214
13518
|
"JSXAttribute[name.name='className']"(node) {
|
|
13215
13519
|
if (node.value === null) return;
|
|
13216
|
-
if (node.value.type ===
|
|
13217
|
-
else if (node.value.type ===
|
|
13218
|
-
if (node.value.expression.type !==
|
|
13520
|
+
if (node.value.type === AST_NODE_TYPES60.Literal) checkClassNode(node.value);
|
|
13521
|
+
else if (node.value.type === AST_NODE_TYPES60.JSXExpressionContainer) {
|
|
13522
|
+
if (node.value.expression.type !== AST_NODE_TYPES60.JSXEmptyExpression) {
|
|
13219
13523
|
checkClassNode(node.value.expression);
|
|
13220
13524
|
}
|
|
13221
13525
|
}
|
|
13222
13526
|
},
|
|
13223
13527
|
CallExpression(node) {
|
|
13224
|
-
if (node.callee.type ===
|
|
13528
|
+
if (node.callee.type === AST_NODE_TYPES60.Identifier && node.callee.name === "require" && node.arguments[0]?.type === AST_NODE_TYPES60.Literal && typeof node.arguments[0].value === "string" && EMAIL_OR_PDF_MODULE_RE.test(node.arguments[0].value)) {
|
|
13225
13529
|
importsEmailOrPdfRenderer = true;
|
|
13226
13530
|
}
|
|
13227
|
-
if (node.callee.type ===
|
|
13531
|
+
if (node.callee.type === AST_NODE_TYPES60.Identifier && CLASS_FNS.has(node.callee.name)) {
|
|
13228
13532
|
for (const arg of node.arguments) {
|
|
13229
|
-
if (arg.type !==
|
|
13533
|
+
if (arg.type !== AST_NODE_TYPES60.SpreadElement) checkClassNode(arg);
|
|
13230
13534
|
}
|
|
13231
13535
|
}
|
|
13232
13536
|
},
|
|
13233
13537
|
VariableDeclarator(node) {
|
|
13234
|
-
if (node.id.type ===
|
|
13538
|
+
if (node.id.type === AST_NODE_TYPES60.Identifier && CLASS_NAME_RE.test(node.id.name)) {
|
|
13235
13539
|
checkClassNode(node.init);
|
|
13236
13540
|
}
|
|
13237
13541
|
},
|
|
@@ -13241,9 +13545,9 @@ var prefer_semantic_colors_default = createRule({
|
|
|
13241
13545
|
},
|
|
13242
13546
|
// SVG artwork colors are exempt; component presentation colors still report.
|
|
13243
13547
|
"JSXAttribute[name.name=/^(fill|stroke|color)$/]"(node) {
|
|
13244
|
-
if (node.value?.type !==
|
|
13548
|
+
if (node.value?.type !== AST_NODE_TYPES60.Literal) return;
|
|
13245
13549
|
const owner = node.parent.name;
|
|
13246
|
-
if (owner.type ===
|
|
13550
|
+
if (owner.type === AST_NODE_TYPES60.JSXIdentifier && SVG_SHAPE_PRIMITIVES.has(owner.name)) {
|
|
13247
13551
|
return;
|
|
13248
13552
|
}
|
|
13249
13553
|
if (typeof node.value.value === "string" && SVG_EXEMPT_COLOR_VALUES.has(node.value.value.toLowerCase())) {
|
|
@@ -13257,7 +13561,7 @@ var prefer_semantic_colors_default = createRule({
|
|
|
13257
13561
|
if (name !== null && STYLE_COLOR_PROPS.has(name)) checkColorValueNode(node.value);
|
|
13258
13562
|
},
|
|
13259
13563
|
ImportExpression(node) {
|
|
13260
|
-
if (node.source.type ===
|
|
13564
|
+
if (node.source.type === AST_NODE_TYPES60.Literal && typeof node.source.value === "string" && EMAIL_OR_PDF_MODULE_RE.test(node.source.value)) {
|
|
13261
13565
|
importsEmailOrPdfRenderer = true;
|
|
13262
13566
|
}
|
|
13263
13567
|
},
|
|
@@ -13459,7 +13763,7 @@ var prefer_server_actions_default = createRule({
|
|
|
13459
13763
|
});
|
|
13460
13764
|
|
|
13461
13765
|
// src/rules/prefer-whole-object-assertion.ts
|
|
13462
|
-
import { AST_NODE_TYPES as
|
|
13766
|
+
import { AST_NODE_TYPES as AST_NODE_TYPES61 } from "@typescript-eslint/utils";
|
|
13463
13767
|
var MERGEABLE_MATCHERS = /* @__PURE__ */ new Set(["toBe", "toEqual", "toStrictEqual"]);
|
|
13464
13768
|
var SYNTHETIC_LITERAL_MATCHERS = /* @__PURE__ */ new Map([
|
|
13465
13769
|
["toBeNull", "null"],
|
|
@@ -13484,11 +13788,11 @@ var PREFER_WHOLE_OBJECT_ASSERTION_DOCUMENTATION = {
|
|
|
13484
13788
|
};
|
|
13485
13789
|
function literalText(node, getText) {
|
|
13486
13790
|
switch (node.type) {
|
|
13487
|
-
case
|
|
13791
|
+
case AST_NODE_TYPES61.Literal:
|
|
13488
13792
|
return "regex" in node ? null : getText(node);
|
|
13489
|
-
case
|
|
13793
|
+
case AST_NODE_TYPES61.TemplateLiteral:
|
|
13490
13794
|
return node.expressions.length === 0 ? getText(node) : null;
|
|
13491
|
-
case
|
|
13795
|
+
case AST_NODE_TYPES61.UnaryExpression:
|
|
13492
13796
|
return NUMERIC_SIGNS2.has(node.operator) && literalText(node.argument, getText) !== null ? getText(node) : null;
|
|
13493
13797
|
default:
|
|
13494
13798
|
return null;
|
|
@@ -13496,15 +13800,15 @@ function literalText(node, getText) {
|
|
|
13496
13800
|
}
|
|
13497
13801
|
function isPureReceiver(node) {
|
|
13498
13802
|
switch (node.type) {
|
|
13499
|
-
case
|
|
13500
|
-
case
|
|
13803
|
+
case AST_NODE_TYPES61.Identifier:
|
|
13804
|
+
case AST_NODE_TYPES61.ThisExpression:
|
|
13501
13805
|
return true;
|
|
13502
|
-
case
|
|
13806
|
+
case AST_NODE_TYPES61.MemberExpression:
|
|
13503
13807
|
if (node.optional) {
|
|
13504
13808
|
return false;
|
|
13505
13809
|
}
|
|
13506
13810
|
if (node.computed) {
|
|
13507
|
-
return node.property.type ===
|
|
13811
|
+
return node.property.type === AST_NODE_TYPES61.Literal && isPureReceiver(node.object);
|
|
13508
13812
|
}
|
|
13509
13813
|
return isPureReceiver(node.object);
|
|
13510
13814
|
default:
|
|
@@ -13512,7 +13816,7 @@ function isPureReceiver(node) {
|
|
|
13512
13816
|
}
|
|
13513
13817
|
}
|
|
13514
13818
|
function literalIndex(node) {
|
|
13515
|
-
if (node.type !==
|
|
13819
|
+
if (node.type !== AST_NODE_TYPES61.Literal || typeof node.value !== "number") {
|
|
13516
13820
|
return null;
|
|
13517
13821
|
}
|
|
13518
13822
|
return Number.isInteger(node.value) && node.value >= 0 ? node.value : null;
|
|
@@ -13520,8 +13824,8 @@ function literalIndex(node) {
|
|
|
13520
13824
|
function propertyAccess(node) {
|
|
13521
13825
|
const path = [];
|
|
13522
13826
|
let current = node;
|
|
13523
|
-
while (current.type ===
|
|
13524
|
-
if (current.property.type !==
|
|
13827
|
+
while (current.type === AST_NODE_TYPES61.MemberExpression && !current.computed && !current.optional) {
|
|
13828
|
+
if (current.property.type !== AST_NODE_TYPES61.Identifier || COLLECTION_PROPERTIES.has(current.property.name) || LITERAL_KEY_HAZARDS.has(current.property.name)) return null;
|
|
13525
13829
|
path.unshift(current.property.name);
|
|
13526
13830
|
current = current.object;
|
|
13527
13831
|
}
|
|
@@ -13549,24 +13853,24 @@ var prefer_whole_object_assertion_default = createRule({
|
|
|
13549
13853
|
}
|
|
13550
13854
|
const { sourceCode } = context;
|
|
13551
13855
|
function parseAssertion(statement) {
|
|
13552
|
-
if (statement.type !==
|
|
13856
|
+
if (statement.type !== AST_NODE_TYPES61.ExpressionStatement) {
|
|
13553
13857
|
return null;
|
|
13554
13858
|
}
|
|
13555
13859
|
const call = statement.expression;
|
|
13556
|
-
if (call.type !==
|
|
13860
|
+
if (call.type !== AST_NODE_TYPES61.CallExpression) {
|
|
13557
13861
|
return null;
|
|
13558
13862
|
}
|
|
13559
13863
|
const callee = call.callee;
|
|
13560
|
-
if (callee.type !==
|
|
13864
|
+
if (callee.type !== AST_NODE_TYPES61.MemberExpression || callee.computed || callee.property.type !== AST_NODE_TYPES61.Identifier) {
|
|
13561
13865
|
return null;
|
|
13562
13866
|
}
|
|
13563
13867
|
const matcher = callee.property.name;
|
|
13564
13868
|
const expectCall = callee.object;
|
|
13565
|
-
if (expectCall.type !==
|
|
13869
|
+
if (expectCall.type !== AST_NODE_TYPES61.CallExpression || expectCall.callee.type !== AST_NODE_TYPES61.Identifier || expectCall.callee.name !== "expect" || expectCall.arguments.length !== 1) {
|
|
13566
13870
|
return null;
|
|
13567
13871
|
}
|
|
13568
13872
|
const actual = expectCall.arguments[0];
|
|
13569
|
-
if (actual === void 0 || actual.type !==
|
|
13873
|
+
if (actual === void 0 || actual.type !== AST_NODE_TYPES61.MemberExpression || actual.optional) {
|
|
13570
13874
|
return null;
|
|
13571
13875
|
}
|
|
13572
13876
|
if (!isPureReceiver(actual.object)) {
|
|
@@ -13595,7 +13899,7 @@ var prefer_whole_object_assertion_default = createRule({
|
|
|
13595
13899
|
return null;
|
|
13596
13900
|
}
|
|
13597
13901
|
const expected = call.arguments[0];
|
|
13598
|
-
if (call.arguments.length !== 1 || expected === void 0 || expected.type ===
|
|
13902
|
+
if (call.arguments.length !== 1 || expected === void 0 || expected.type === AST_NODE_TYPES61.SpreadElement) {
|
|
13599
13903
|
return null;
|
|
13600
13904
|
}
|
|
13601
13905
|
const literal = literalText(expected, (node) => sourceCode.getText(node));
|
|
@@ -13736,7 +14040,7 @@ var prefer_whole_object_assertion_default = createRule({
|
|
|
13736
14040
|
});
|
|
13737
14041
|
|
|
13738
14042
|
// src/rules/repeated-static-call-cases.ts
|
|
13739
|
-
import { AST_NODE_TYPES as
|
|
14043
|
+
import { AST_NODE_TYPES as AST_NODE_TYPES62, ASTUtils as ASTUtils18 } from "@typescript-eslint/utils";
|
|
13740
14044
|
var REPEATED_STATIC_CALL_CASES_DOCUMENTATION = {
|
|
13741
14045
|
summary: "Report three or more consecutive literal call assertions that should be independently named test cases.",
|
|
13742
14046
|
rationale: "Copy-pasted cases obscure the input table and stop later cases from being reported after the first failure.",
|
|
@@ -13757,67 +14061,67 @@ var EXPECT_MODIFIERS = /* @__PURE__ */ new Set(["not", "rejects", "resolves"]);
|
|
|
13757
14061
|
var SNAPSHOT_MATCHERS = /snapshot/iu;
|
|
13758
14062
|
var MIN_CASES2 = 3;
|
|
13759
14063
|
function staticMemberName5(node) {
|
|
13760
|
-
if (!node.computed && node.property.type ===
|
|
13761
|
-
if (node.computed && node.property.type ===
|
|
14064
|
+
if (!node.computed && node.property.type === AST_NODE_TYPES62.Identifier) return node.property.name;
|
|
14065
|
+
if (node.computed && node.property.type === AST_NODE_TYPES62.Literal && typeof node.property.value === "string") return node.property.value;
|
|
13762
14066
|
return null;
|
|
13763
14067
|
}
|
|
13764
|
-
function
|
|
14068
|
+
function importedName6(identifier, context, modules) {
|
|
13765
14069
|
const variable = ASTUtils18.findVariable(context.sourceCode.getScope(identifier), identifier.name);
|
|
13766
14070
|
if (variable === null || variable.defs.length === 0) return identifier.name;
|
|
13767
14071
|
for (const definition of variable.defs) {
|
|
13768
|
-
if (definition.node.type !==
|
|
14072
|
+
if (definition.node.type !== AST_NODE_TYPES62.ImportSpecifier) continue;
|
|
13769
14073
|
const declaration = definition.node.parent;
|
|
13770
|
-
if (declaration.type !==
|
|
14074
|
+
if (declaration.type !== AST_NODE_TYPES62.ImportDeclaration || typeof declaration.source.value !== "string" || !modules.has(declaration.source.value)) continue;
|
|
13771
14075
|
const imported = definition.node.imported;
|
|
13772
|
-
return imported.type ===
|
|
14076
|
+
return imported.type === AST_NODE_TYPES62.Identifier ? imported.name : String(imported.value);
|
|
13773
14077
|
}
|
|
13774
14078
|
return null;
|
|
13775
14079
|
}
|
|
13776
14080
|
function isDirectTestCallback2(node, context) {
|
|
13777
|
-
if (node.type !==
|
|
14081
|
+
if (node.type !== AST_NODE_TYPES62.ArrowFunctionExpression && node.type !== AST_NODE_TYPES62.FunctionExpression) return false;
|
|
13778
14082
|
const call = node.parent;
|
|
13779
|
-
if (call?.type !==
|
|
14083
|
+
if (call?.type !== AST_NODE_TYPES62.CallExpression || !call.arguments.includes(node)) return false;
|
|
13780
14084
|
const root = testRoot2(call.callee);
|
|
13781
|
-
return root !== null && TEST_NAMES2.has(
|
|
14085
|
+
return root !== null && TEST_NAMES2.has(importedName6(root, context, TEST_MODULES4) ?? "");
|
|
13782
14086
|
}
|
|
13783
14087
|
function testRoot2(callee) {
|
|
13784
|
-
if (callee.type ===
|
|
13785
|
-
if (callee.type !==
|
|
14088
|
+
if (callee.type === AST_NODE_TYPES62.Identifier) return callee;
|
|
14089
|
+
if (callee.type !== AST_NODE_TYPES62.MemberExpression) return null;
|
|
13786
14090
|
const modifier = staticMemberName5(callee);
|
|
13787
14091
|
return modifier !== null && TEST_MODIFIERS4.has(modifier) ? testRoot2(callee.object) : null;
|
|
13788
14092
|
}
|
|
13789
14093
|
function isStatic(node) {
|
|
13790
|
-
if (node.type ===
|
|
14094
|
+
if (node.type === AST_NODE_TYPES62.TSAsExpression || node.type === AST_NODE_TYPES62.TSTypeAssertion || node.type === AST_NODE_TYPES62.TSSatisfiesExpression || node.type === AST_NODE_TYPES62.TSNonNullExpression) return isStatic(node.expression);
|
|
13791
14095
|
switch (node.type) {
|
|
13792
|
-
case
|
|
14096
|
+
case AST_NODE_TYPES62.Literal:
|
|
13793
14097
|
return true;
|
|
13794
|
-
case
|
|
14098
|
+
case AST_NODE_TYPES62.TemplateLiteral:
|
|
13795
14099
|
return node.expressions.length === 0;
|
|
13796
|
-
case
|
|
14100
|
+
case AST_NODE_TYPES62.UnaryExpression:
|
|
13797
14101
|
return (node.operator === "+" || node.operator === "-") && isStatic(node.argument);
|
|
13798
|
-
case
|
|
13799
|
-
return node.elements.every((item) => item !== null && item.type !==
|
|
13800
|
-
case
|
|
13801
|
-
return node.properties.every((property) => property.type ===
|
|
14102
|
+
case AST_NODE_TYPES62.ArrayExpression:
|
|
14103
|
+
return node.elements.every((item) => item !== null && item.type !== AST_NODE_TYPES62.SpreadElement && isStatic(item));
|
|
14104
|
+
case AST_NODE_TYPES62.ObjectExpression:
|
|
14105
|
+
return node.properties.every((property) => property.type === AST_NODE_TYPES62.Property && !property.computed && property.kind === "init" && property.value.type !== AST_NODE_TYPES62.AssignmentPattern && isStatic(property.value));
|
|
13802
14106
|
default:
|
|
13803
14107
|
return false;
|
|
13804
14108
|
}
|
|
13805
14109
|
}
|
|
13806
14110
|
function staticShape(node) {
|
|
13807
|
-
if (node.type ===
|
|
14111
|
+
if (node.type === AST_NODE_TYPES62.TSAsExpression || node.type === AST_NODE_TYPES62.TSTypeAssertion || node.type === AST_NODE_TYPES62.TSSatisfiesExpression || node.type === AST_NODE_TYPES62.TSNonNullExpression) return staticShape(node.expression);
|
|
13808
14112
|
switch (node.type) {
|
|
13809
|
-
case
|
|
14113
|
+
case AST_NODE_TYPES62.Literal:
|
|
13810
14114
|
return `literal:${typeof node.value}`;
|
|
13811
|
-
case
|
|
14115
|
+
case AST_NODE_TYPES62.TemplateLiteral:
|
|
13812
14116
|
return "template";
|
|
13813
|
-
case
|
|
14117
|
+
case AST_NODE_TYPES62.UnaryExpression:
|
|
13814
14118
|
return `unary:${node.operator}:${staticShape(node.argument)}`;
|
|
13815
|
-
case
|
|
13816
|
-
return `array(${node.elements.map((item) => item === null || item.type ===
|
|
13817
|
-
case
|
|
14119
|
+
case AST_NODE_TYPES62.ArrayExpression:
|
|
14120
|
+
return `array(${node.elements.map((item) => item === null || item.type === AST_NODE_TYPES62.SpreadElement ? "invalid" : staticShape(item)).join(",")})`;
|
|
14121
|
+
case AST_NODE_TYPES62.ObjectExpression:
|
|
13818
14122
|
return `object(${node.properties.map((property) => {
|
|
13819
|
-
if (property.type !==
|
|
13820
|
-
const key = property.key.type ===
|
|
14123
|
+
if (property.type !== AST_NODE_TYPES62.Property || property.computed || property.value.type === AST_NODE_TYPES62.AssignmentPattern) return "invalid";
|
|
14124
|
+
const key = property.key.type === AST_NODE_TYPES62.Identifier ? property.key.name : String(property.key.value);
|
|
13821
14125
|
return `${key}:${staticShape(property.value)}`;
|
|
13822
14126
|
}).join(",")})`;
|
|
13823
14127
|
default:
|
|
@@ -13825,16 +14129,16 @@ function staticShape(node) {
|
|
|
13825
14129
|
}
|
|
13826
14130
|
}
|
|
13827
14131
|
function assertionShape(statement, context) {
|
|
13828
|
-
if (statement.type !==
|
|
14132
|
+
if (statement.type !== AST_NODE_TYPES62.ExpressionStatement || statement.expression.type !== AST_NODE_TYPES62.CallExpression) return null;
|
|
13829
14133
|
const matcherCall = statement.expression;
|
|
13830
|
-
if (matcherCall.callee.type !==
|
|
14134
|
+
if (matcherCall.callee.type !== AST_NODE_TYPES62.MemberExpression || matcherCall.callee.computed || matcherCall.callee.property.type !== AST_NODE_TYPES62.Identifier || matcherCall.arguments.length !== 1) return null;
|
|
13831
14135
|
const matcher = matcherCall.callee.property.name;
|
|
13832
14136
|
if (SNAPSHOT_MATCHERS.test(matcher)) return null;
|
|
13833
14137
|
const chain = expectCallFromMatcher(matcherCall.callee);
|
|
13834
|
-
if (chain === null || chain.call.callee.type !==
|
|
14138
|
+
if (chain === null || chain.call.callee.type !== AST_NODE_TYPES62.Identifier || importedName6(chain.call.callee, context, ASSERTION_MODULES3) !== "expect" || chain.call.arguments.length !== 1) return null;
|
|
13835
14139
|
const observed = chain.call.arguments[0];
|
|
13836
14140
|
const expected = matcherCall.arguments[0];
|
|
13837
|
-
if (observed?.type !==
|
|
14141
|
+
if (observed?.type !== AST_NODE_TYPES62.CallExpression || observed.callee.type !== AST_NODE_TYPES62.Identifier || observed.arguments.length === 0 || observed.arguments.some((arg) => arg.type === AST_NODE_TYPES62.SpreadElement || !isStatic(arg)) || expected?.type === AST_NODE_TYPES62.SpreadElement || expected === void 0 || !isStatic(expected)) return null;
|
|
13838
14142
|
const skeleton = `${observed.callee.name}/${observed.arguments.map((item) => staticShape(item)).join(",")}/${chain.modifiers.join(".")}/${matcher}/${staticShape(expected)}`;
|
|
13839
14143
|
const values = [...observed.arguments, expected].map((item) => context.sourceCode.getText(item)).join("\0");
|
|
13840
14144
|
return { statement, skeleton, values };
|
|
@@ -13842,13 +14146,13 @@ function assertionShape(statement, context) {
|
|
|
13842
14146
|
function expectCallFromMatcher(node) {
|
|
13843
14147
|
const modifiers = [];
|
|
13844
14148
|
let receiver = node.object;
|
|
13845
|
-
while (receiver.type ===
|
|
14149
|
+
while (receiver.type === AST_NODE_TYPES62.MemberExpression) {
|
|
13846
14150
|
const modifier = staticMemberName5(receiver);
|
|
13847
14151
|
if (modifier === null || !EXPECT_MODIFIERS.has(modifier)) return null;
|
|
13848
14152
|
modifiers.unshift(modifier);
|
|
13849
14153
|
receiver = receiver.object;
|
|
13850
14154
|
}
|
|
13851
|
-
return receiver.type ===
|
|
14155
|
+
return receiver.type === AST_NODE_TYPES62.CallExpression ? { call: receiver, modifiers } : null;
|
|
13852
14156
|
}
|
|
13853
14157
|
var repeated_static_call_cases_default = createRule({
|
|
13854
14158
|
name: "repeated-static-call-cases",
|
|
@@ -13868,7 +14172,7 @@ var repeated_static_call_cases_default = createRule({
|
|
|
13868
14172
|
return {
|
|
13869
14173
|
"CallExpression > ArrowFunctionExpression, CallExpression > FunctionExpression"(node) {
|
|
13870
14174
|
const call = node.parent;
|
|
13871
|
-
if (call?.type ===
|
|
14175
|
+
if (call?.type === AST_NODE_TYPES62.CallExpression) {
|
|
13872
14176
|
const duplicate = duplicateTestBodyCandidate(call, sourceCode);
|
|
13873
14177
|
if (duplicate !== null && duplicate.body === node) {
|
|
13874
14178
|
const groups = duplicateGroups.get(duplicate.container) ?? /* @__PURE__ */ new Map();
|
|
@@ -13878,7 +14182,7 @@ var repeated_static_call_cases_default = createRule({
|
|
|
13878
14182
|
duplicateGroups.set(duplicate.container, groups);
|
|
13879
14183
|
}
|
|
13880
14184
|
}
|
|
13881
|
-
if (!isDirectTestCallback2(node, context) || node.body.type !==
|
|
14185
|
+
if (!isDirectTestCallback2(node, context) || node.body.type !== AST_NODE_TYPES62.BlockStatement) return;
|
|
13882
14186
|
let run = [];
|
|
13883
14187
|
const flush = () => {
|
|
13884
14188
|
if (run.length >= MIN_CASES2 && new Set(run.map((item) => item.values)).size > 1) {
|
|
@@ -13919,7 +14223,7 @@ var repeated_static_call_cases_default = createRule({
|
|
|
13919
14223
|
});
|
|
13920
14224
|
|
|
13921
14225
|
// src/rules/prefer-zod-infer.ts
|
|
13922
|
-
import { AST_NODE_TYPES as
|
|
14226
|
+
import { AST_NODE_TYPES as AST_NODE_TYPES63 } from "@typescript-eslint/utils";
|
|
13923
14227
|
var PREFER_ZOD_INFER_DOCUMENTATION = {
|
|
13924
14228
|
summary: "Derive a type from its Zod schema with `z.infer` instead of hand-writing a twin declaration beside it.",
|
|
13925
14229
|
rationale: "A derived type stays synchronized when the runtime schema changes.",
|
|
@@ -13972,47 +14276,47 @@ var ZOD_TYPE_CONSTRAINTS = /* @__PURE__ */ new Set([
|
|
|
13972
14276
|
"Schema"
|
|
13973
14277
|
]);
|
|
13974
14278
|
var LEAF_NODE_TYPES = {
|
|
13975
|
-
string: [
|
|
13976
|
-
email: [
|
|
13977
|
-
url: [
|
|
13978
|
-
uuid: [
|
|
13979
|
-
ulid: [
|
|
13980
|
-
cuid: [
|
|
13981
|
-
cuid2: [
|
|
13982
|
-
nanoid: [
|
|
13983
|
-
iso: [
|
|
13984
|
-
number: [
|
|
13985
|
-
int: [
|
|
13986
|
-
float32: [
|
|
13987
|
-
float64: [
|
|
13988
|
-
boolean: [
|
|
13989
|
-
bigint: [
|
|
13990
|
-
symbol: [
|
|
13991
|
-
any: [
|
|
13992
|
-
unknown: [
|
|
13993
|
-
never: [
|
|
13994
|
-
void: [
|
|
13995
|
-
null: [
|
|
13996
|
-
undefined: [
|
|
13997
|
-
literal: [
|
|
13998
|
-
date: [
|
|
13999
|
-
array: [
|
|
14000
|
-
tuple: [
|
|
14001
|
-
object: [
|
|
14002
|
-
strictObject: [
|
|
14003
|
-
looseObject: [
|
|
14004
|
-
record: [
|
|
14005
|
-
map: [
|
|
14006
|
-
set: [
|
|
14007
|
-
promise: [
|
|
14008
|
-
enum: [
|
|
14009
|
-
nativeEnum: [
|
|
14010
|
-
union: [
|
|
14011
|
-
discriminatedUnion: [
|
|
14012
|
-
intersection: [
|
|
14279
|
+
string: [AST_NODE_TYPES63.TSStringKeyword],
|
|
14280
|
+
email: [AST_NODE_TYPES63.TSStringKeyword],
|
|
14281
|
+
url: [AST_NODE_TYPES63.TSStringKeyword],
|
|
14282
|
+
uuid: [AST_NODE_TYPES63.TSStringKeyword],
|
|
14283
|
+
ulid: [AST_NODE_TYPES63.TSStringKeyword],
|
|
14284
|
+
cuid: [AST_NODE_TYPES63.TSStringKeyword],
|
|
14285
|
+
cuid2: [AST_NODE_TYPES63.TSStringKeyword],
|
|
14286
|
+
nanoid: [AST_NODE_TYPES63.TSStringKeyword],
|
|
14287
|
+
iso: [AST_NODE_TYPES63.TSStringKeyword],
|
|
14288
|
+
number: [AST_NODE_TYPES63.TSNumberKeyword],
|
|
14289
|
+
int: [AST_NODE_TYPES63.TSNumberKeyword],
|
|
14290
|
+
float32: [AST_NODE_TYPES63.TSNumberKeyword],
|
|
14291
|
+
float64: [AST_NODE_TYPES63.TSNumberKeyword],
|
|
14292
|
+
boolean: [AST_NODE_TYPES63.TSBooleanKeyword],
|
|
14293
|
+
bigint: [AST_NODE_TYPES63.TSBigIntKeyword],
|
|
14294
|
+
symbol: [AST_NODE_TYPES63.TSSymbolKeyword],
|
|
14295
|
+
any: [AST_NODE_TYPES63.TSAnyKeyword],
|
|
14296
|
+
unknown: [AST_NODE_TYPES63.TSUnknownKeyword],
|
|
14297
|
+
never: [AST_NODE_TYPES63.TSNeverKeyword],
|
|
14298
|
+
void: [AST_NODE_TYPES63.TSVoidKeyword],
|
|
14299
|
+
null: [AST_NODE_TYPES63.TSNullKeyword],
|
|
14300
|
+
undefined: [AST_NODE_TYPES63.TSUndefinedKeyword],
|
|
14301
|
+
literal: [AST_NODE_TYPES63.TSLiteralType],
|
|
14302
|
+
date: [AST_NODE_TYPES63.TSTypeReference],
|
|
14303
|
+
array: [AST_NODE_TYPES63.TSArrayType, AST_NODE_TYPES63.TSTypeReference],
|
|
14304
|
+
tuple: [AST_NODE_TYPES63.TSTupleType],
|
|
14305
|
+
object: [AST_NODE_TYPES63.TSTypeLiteral, AST_NODE_TYPES63.TSTypeReference],
|
|
14306
|
+
strictObject: [AST_NODE_TYPES63.TSTypeLiteral, AST_NODE_TYPES63.TSTypeReference],
|
|
14307
|
+
looseObject: [AST_NODE_TYPES63.TSTypeLiteral, AST_NODE_TYPES63.TSTypeReference],
|
|
14308
|
+
record: [AST_NODE_TYPES63.TSTypeReference, AST_NODE_TYPES63.TSTypeLiteral],
|
|
14309
|
+
map: [AST_NODE_TYPES63.TSTypeReference],
|
|
14310
|
+
set: [AST_NODE_TYPES63.TSTypeReference],
|
|
14311
|
+
promise: [AST_NODE_TYPES63.TSTypeReference],
|
|
14312
|
+
enum: [AST_NODE_TYPES63.TSUnionType, AST_NODE_TYPES63.TSTypeReference, AST_NODE_TYPES63.TSLiteralType],
|
|
14313
|
+
nativeEnum: [AST_NODE_TYPES63.TSUnionType, AST_NODE_TYPES63.TSTypeReference, AST_NODE_TYPES63.TSLiteralType],
|
|
14314
|
+
union: [AST_NODE_TYPES63.TSUnionType, AST_NODE_TYPES63.TSTypeReference],
|
|
14315
|
+
discriminatedUnion: [AST_NODE_TYPES63.TSUnionType, AST_NODE_TYPES63.TSTypeReference],
|
|
14316
|
+
intersection: [AST_NODE_TYPES63.TSIntersectionType, AST_NODE_TYPES63.TSTypeReference]
|
|
14013
14317
|
};
|
|
14014
14318
|
function primitiveLiteralKey(node) {
|
|
14015
|
-
if (node.type !==
|
|
14319
|
+
if (node.type !== AST_NODE_TYPES63.Literal) {
|
|
14016
14320
|
return null;
|
|
14017
14321
|
}
|
|
14018
14322
|
if (node.value === null) {
|
|
@@ -14044,13 +14348,13 @@ function staticZodDomain(leaf, call) {
|
|
|
14044
14348
|
}
|
|
14045
14349
|
if (leaf === "literal") {
|
|
14046
14350
|
const [argument] = call.arguments;
|
|
14047
|
-
if (argument === void 0 || argument.type ===
|
|
14351
|
+
if (argument === void 0 || argument.type === AST_NODE_TYPES63.SpreadElement) {
|
|
14048
14352
|
return null;
|
|
14049
14353
|
}
|
|
14050
|
-
if (argument.type ===
|
|
14354
|
+
if (argument.type === AST_NODE_TYPES63.ArrayExpression) {
|
|
14051
14355
|
return exactDomain(
|
|
14052
14356
|
argument.elements.map(
|
|
14053
|
-
(element) => element === null || element.type ===
|
|
14357
|
+
(element) => element === null || element.type === AST_NODE_TYPES63.SpreadElement ? null : primitiveLiteralKey(element)
|
|
14054
14358
|
)
|
|
14055
14359
|
);
|
|
14056
14360
|
}
|
|
@@ -14058,13 +14362,13 @@ function staticZodDomain(leaf, call) {
|
|
|
14058
14362
|
}
|
|
14059
14363
|
if (leaf === "enum") {
|
|
14060
14364
|
const [argument] = call.arguments;
|
|
14061
|
-
if (argument === void 0 || argument.type ===
|
|
14365
|
+
if (argument === void 0 || argument.type === AST_NODE_TYPES63.SpreadElement) {
|
|
14062
14366
|
return null;
|
|
14063
14367
|
}
|
|
14064
|
-
if (argument.type ===
|
|
14368
|
+
if (argument.type === AST_NODE_TYPES63.ArrayExpression) {
|
|
14065
14369
|
return exactDomain(
|
|
14066
14370
|
argument.elements.map((element) => {
|
|
14067
|
-
if (element === null || element.type ===
|
|
14371
|
+
if (element === null || element.type === AST_NODE_TYPES63.SpreadElement) {
|
|
14068
14372
|
return null;
|
|
14069
14373
|
}
|
|
14070
14374
|
const key = primitiveLiteralKey(element);
|
|
@@ -14072,10 +14376,10 @@ function staticZodDomain(leaf, call) {
|
|
|
14072
14376
|
})
|
|
14073
14377
|
);
|
|
14074
14378
|
}
|
|
14075
|
-
if (argument.type ===
|
|
14379
|
+
if (argument.type === AST_NODE_TYPES63.ObjectExpression) {
|
|
14076
14380
|
return exactDomain(
|
|
14077
14381
|
argument.properties.map((property) => {
|
|
14078
|
-
if (property.type !==
|
|
14382
|
+
if (property.type !== AST_NODE_TYPES63.Property || property.computed || property.kind !== "init" || property.method || property.shorthand) {
|
|
14079
14383
|
return null;
|
|
14080
14384
|
}
|
|
14081
14385
|
const key = primitiveLiteralKey(property.value);
|
|
@@ -14102,15 +14406,15 @@ function sameDomain(left, right) {
|
|
|
14102
14406
|
return true;
|
|
14103
14407
|
}
|
|
14104
14408
|
function isExportedDeclaration(node) {
|
|
14105
|
-
return node.parent?.type ===
|
|
14409
|
+
return node.parent?.type === AST_NODE_TYPES63.ExportNamedDeclaration;
|
|
14106
14410
|
}
|
|
14107
14411
|
function isModuleLevelConst(node) {
|
|
14108
14412
|
const declaration = node.parent;
|
|
14109
|
-
if (declaration.type !==
|
|
14413
|
+
if (declaration.type !== AST_NODE_TYPES63.VariableDeclaration || declaration.kind !== "const") {
|
|
14110
14414
|
return false;
|
|
14111
14415
|
}
|
|
14112
14416
|
const container = declaration.parent;
|
|
14113
|
-
return container.type ===
|
|
14417
|
+
return container.type === AST_NODE_TYPES63.Program || container.type === AST_NODE_TYPES63.ExportNamedDeclaration && container.parent.type === AST_NODE_TYPES63.Program;
|
|
14114
14418
|
}
|
|
14115
14419
|
function normalizeSchemaName(name) {
|
|
14116
14420
|
return name.replace(/Schema$/i, "").replace(/^Z(?=[A-Z])/, "").toLowerCase();
|
|
@@ -14119,20 +14423,20 @@ function normalizeTypeName(name) {
|
|
|
14119
14423
|
return name.replace(/Type$/, "").toLowerCase();
|
|
14120
14424
|
}
|
|
14121
14425
|
function unwrapNullish(annotation) {
|
|
14122
|
-
if (annotation.type !==
|
|
14426
|
+
if (annotation.type !== AST_NODE_TYPES63.TSUnionType) {
|
|
14123
14427
|
return {
|
|
14124
14428
|
core: annotation,
|
|
14125
|
-
nullable: annotation.type ===
|
|
14429
|
+
nullable: annotation.type === AST_NODE_TYPES63.TSNullKeyword
|
|
14126
14430
|
};
|
|
14127
14431
|
}
|
|
14128
14432
|
const rest = [];
|
|
14129
14433
|
let nullable = false;
|
|
14130
14434
|
for (const member of annotation.types) {
|
|
14131
|
-
if (member.type ===
|
|
14435
|
+
if (member.type === AST_NODE_TYPES63.TSNullKeyword) {
|
|
14132
14436
|
nullable = true;
|
|
14133
14437
|
continue;
|
|
14134
14438
|
}
|
|
14135
|
-
if (member.type ===
|
|
14439
|
+
if (member.type === AST_NODE_TYPES63.TSUndefinedKeyword) {
|
|
14136
14440
|
continue;
|
|
14137
14441
|
}
|
|
14138
14442
|
rest.push(member);
|
|
@@ -14166,18 +14470,18 @@ function leafAgrees(field, annotation) {
|
|
|
14166
14470
|
return null;
|
|
14167
14471
|
}
|
|
14168
14472
|
if (leaf === "date") {
|
|
14169
|
-
return core.type ===
|
|
14473
|
+
return core.type === AST_NODE_TYPES63.TSTypeReference && core.typeName.type === AST_NODE_TYPES63.Identifier && core.typeName.name === "Date";
|
|
14170
14474
|
}
|
|
14171
14475
|
return expected.includes(core.type);
|
|
14172
14476
|
}
|
|
14173
14477
|
function typeLiteralDomain(annotation) {
|
|
14174
|
-
const members = annotation.type ===
|
|
14478
|
+
const members = annotation.type === AST_NODE_TYPES63.TSUnionType ? annotation.types : [annotation];
|
|
14175
14479
|
const keys = [];
|
|
14176
14480
|
for (const member of members) {
|
|
14177
|
-
if (member.type ===
|
|
14481
|
+
if (member.type === AST_NODE_TYPES63.TSNullKeyword) {
|
|
14178
14482
|
continue;
|
|
14179
14483
|
}
|
|
14180
|
-
if (member.type !==
|
|
14484
|
+
if (member.type !== AST_NODE_TYPES63.TSLiteralType) {
|
|
14181
14485
|
return null;
|
|
14182
14486
|
}
|
|
14183
14487
|
keys.push(primitiveLiteralKey(member.literal));
|
|
@@ -14185,11 +14489,11 @@ function typeLiteralDomain(annotation) {
|
|
|
14185
14489
|
return exactDomain(keys);
|
|
14186
14490
|
}
|
|
14187
14491
|
function staticStringUnionDomain(node) {
|
|
14188
|
-
if (node.type !==
|
|
14492
|
+
if (node.type !== AST_NODE_TYPES63.TSUnionType) {
|
|
14189
14493
|
return null;
|
|
14190
14494
|
}
|
|
14191
14495
|
const keys = node.types.map((member) => {
|
|
14192
|
-
if (member.type !==
|
|
14496
|
+
if (member.type !== AST_NODE_TYPES63.TSLiteralType) {
|
|
14193
14497
|
return null;
|
|
14194
14498
|
}
|
|
14195
14499
|
const key = primitiveLiteralKey(member.literal);
|
|
@@ -14257,14 +14561,14 @@ var prefer_zod_infer_default = createRule({
|
|
|
14257
14561
|
function zodCallChain(node) {
|
|
14258
14562
|
const chain = [];
|
|
14259
14563
|
let current = node;
|
|
14260
|
-
while (current.type ===
|
|
14564
|
+
while (current.type === AST_NODE_TYPES63.CallExpression) {
|
|
14261
14565
|
const callee = current.callee;
|
|
14262
|
-
if (callee.type !==
|
|
14566
|
+
if (callee.type !== AST_NODE_TYPES63.MemberExpression || callee.computed || callee.property.type !== AST_NODE_TYPES63.Identifier) {
|
|
14263
14567
|
return null;
|
|
14264
14568
|
}
|
|
14265
14569
|
chain.push(current);
|
|
14266
14570
|
const receiver = callee.object;
|
|
14267
|
-
if (receiver.type ===
|
|
14571
|
+
if (receiver.type === AST_NODE_TYPES63.Identifier) {
|
|
14268
14572
|
return zodNamespaces.has(receiver.name) ? chain.reverse() : null;
|
|
14269
14573
|
}
|
|
14270
14574
|
current = receiver;
|
|
@@ -14273,14 +14577,14 @@ var prefer_zod_infer_default = createRule({
|
|
|
14273
14577
|
}
|
|
14274
14578
|
function methodName2(call) {
|
|
14275
14579
|
const callee = call.callee;
|
|
14276
|
-
return callee.type ===
|
|
14580
|
+
return callee.type === AST_NODE_TYPES63.MemberExpression && callee.property.type === AST_NODE_TYPES63.Identifier ? callee.property.name : "";
|
|
14277
14581
|
}
|
|
14278
14582
|
function recordZodImport(node) {
|
|
14279
14583
|
if (!isZodModule(node.source.value)) {
|
|
14280
14584
|
return;
|
|
14281
14585
|
}
|
|
14282
14586
|
for (const specifier of node.specifiers) {
|
|
14283
|
-
if (specifier.type ===
|
|
14587
|
+
if (specifier.type === AST_NODE_TYPES63.ImportNamespaceSpecifier || specifier.type === AST_NODE_TYPES63.ImportDefaultSpecifier || specifier.type === AST_NODE_TYPES63.ImportSpecifier && specifier.imported.type === AST_NODE_TYPES63.Identifier && specifier.imported.name === "z") {
|
|
14284
14588
|
zodNamespaces.add(specifier.local.name);
|
|
14285
14589
|
}
|
|
14286
14590
|
}
|
|
@@ -14290,13 +14594,13 @@ var prefer_zod_infer_default = createRule({
|
|
|
14290
14594
|
let current = node;
|
|
14291
14595
|
let leaf = null;
|
|
14292
14596
|
let leafCall = null;
|
|
14293
|
-
while (current.type ===
|
|
14597
|
+
while (current.type === AST_NODE_TYPES63.CallExpression) {
|
|
14294
14598
|
const callee = current.callee;
|
|
14295
|
-
if (callee.type !==
|
|
14599
|
+
if (callee.type !== AST_NODE_TYPES63.MemberExpression || callee.computed || callee.property.type !== AST_NODE_TYPES63.Identifier) {
|
|
14296
14600
|
break;
|
|
14297
14601
|
}
|
|
14298
14602
|
const receiver = callee.object;
|
|
14299
|
-
if (receiver.type ===
|
|
14603
|
+
if (receiver.type === AST_NODE_TYPES63.Identifier && zodNamespaces.has(receiver.name)) {
|
|
14300
14604
|
leaf = callee.property.name;
|
|
14301
14605
|
leafCall = current;
|
|
14302
14606
|
break;
|
|
@@ -14327,20 +14631,20 @@ var prefer_zod_infer_default = createRule({
|
|
|
14327
14631
|
return domain instanceof Set && domain.size >= 2 ? domain : null;
|
|
14328
14632
|
}
|
|
14329
14633
|
function inferredSchemaName(node) {
|
|
14330
|
-
if (node.type !==
|
|
14634
|
+
if (node.type !== AST_NODE_TYPES63.TSTypeReference || node.typeName.type !== AST_NODE_TYPES63.TSQualifiedName || node.typeName.left.type !== AST_NODE_TYPES63.Identifier || !zodNamespaces.has(node.typeName.left.name) || node.typeName.right.name !== "infer") {
|
|
14331
14635
|
return null;
|
|
14332
14636
|
}
|
|
14333
14637
|
const arguments_ = node.typeArguments?.params ?? [];
|
|
14334
14638
|
const [argument] = arguments_;
|
|
14335
|
-
return arguments_.length === 1 && argument?.type ===
|
|
14639
|
+
return arguments_.length === 1 && argument?.type === AST_NODE_TYPES63.TSTypeQuery && argument.exprName.type === AST_NODE_TYPES63.Identifier ? argument.exprName.name : null;
|
|
14336
14640
|
}
|
|
14337
14641
|
function recordLiteralUnions(members, owner, ownerName, exported) {
|
|
14338
14642
|
for (const member of members) {
|
|
14339
|
-
if (member.type !==
|
|
14643
|
+
if (member.type !== AST_NODE_TYPES63.TSPropertySignature || member.computed || member.optional || member.readonly || member.typeAnnotation === void 0) {
|
|
14340
14644
|
continue;
|
|
14341
14645
|
}
|
|
14342
14646
|
const key = member.key;
|
|
14343
|
-
const propertyName5 = key.type ===
|
|
14647
|
+
const propertyName5 = key.type === AST_NODE_TYPES63.Identifier ? key.name : key.type === AST_NODE_TYPES63.Literal && typeof key.value === "string" ? key.value : null;
|
|
14344
14648
|
if (propertyName5 === null) {
|
|
14345
14649
|
continue;
|
|
14346
14650
|
}
|
|
@@ -14350,7 +14654,7 @@ var prefer_zod_infer_default = createRule({
|
|
|
14350
14654
|
}
|
|
14351
14655
|
const annotation = member.typeAnnotation.typeAnnotation;
|
|
14352
14656
|
const domain = staticStringUnionDomain(annotation);
|
|
14353
|
-
if (domain === null || annotation.type !==
|
|
14657
|
+
if (domain === null || annotation.type !== AST_NODE_TYPES63.TSUnionType) {
|
|
14354
14658
|
continue;
|
|
14355
14659
|
}
|
|
14356
14660
|
literalUnionOccurrences.push({
|
|
@@ -14381,16 +14685,16 @@ var prefer_zod_infer_default = createRule({
|
|
|
14381
14685
|
return null;
|
|
14382
14686
|
}
|
|
14383
14687
|
const shape = base.arguments[0];
|
|
14384
|
-
if (shape === void 0 || shape.type !==
|
|
14688
|
+
if (shape === void 0 || shape.type !== AST_NODE_TYPES63.ObjectExpression) {
|
|
14385
14689
|
return null;
|
|
14386
14690
|
}
|
|
14387
14691
|
const fields = /* @__PURE__ */ new Map();
|
|
14388
14692
|
for (const property of shape.properties) {
|
|
14389
|
-
if (property.type !==
|
|
14693
|
+
if (property.type !== AST_NODE_TYPES63.Property || property.computed) {
|
|
14390
14694
|
return null;
|
|
14391
14695
|
}
|
|
14392
14696
|
const { key } = property;
|
|
14393
|
-
const name = key.type ===
|
|
14697
|
+
const name = key.type === AST_NODE_TYPES63.Identifier ? key.name : key.type === AST_NODE_TYPES63.Literal && typeof key.value === "string" ? key.value : null;
|
|
14394
14698
|
if (name === null) {
|
|
14395
14699
|
return null;
|
|
14396
14700
|
}
|
|
@@ -14401,11 +14705,11 @@ var prefer_zod_infer_default = createRule({
|
|
|
14401
14705
|
function typeMembers(members) {
|
|
14402
14706
|
const result = /* @__PURE__ */ new Map();
|
|
14403
14707
|
for (const member of members) {
|
|
14404
|
-
if (member.type !==
|
|
14708
|
+
if (member.type !== AST_NODE_TYPES63.TSPropertySignature || member.computed) {
|
|
14405
14709
|
return null;
|
|
14406
14710
|
}
|
|
14407
14711
|
const { key } = member;
|
|
14408
|
-
const name = key.type ===
|
|
14712
|
+
const name = key.type === AST_NODE_TYPES63.Identifier ? key.name : key.type === AST_NODE_TYPES63.Literal && typeof key.value === "string" ? key.value : null;
|
|
14409
14713
|
if (name === null) {
|
|
14410
14714
|
return null;
|
|
14411
14715
|
}
|
|
@@ -14420,8 +14724,8 @@ var prefer_zod_infer_default = createRule({
|
|
|
14420
14724
|
return result.size === 0 ? null : result;
|
|
14421
14725
|
}
|
|
14422
14726
|
function collectConstrainedNames(node) {
|
|
14423
|
-
if (node.type ===
|
|
14424
|
-
if (node.typeName.type ===
|
|
14727
|
+
if (node.type === AST_NODE_TYPES63.TSTypeReference) {
|
|
14728
|
+
if (node.typeName.type === AST_NODE_TYPES63.Identifier) {
|
|
14425
14729
|
constrainedTypeNames.add(node.typeName.name);
|
|
14426
14730
|
}
|
|
14427
14731
|
for (const argument of node.typeArguments?.params ?? []) {
|
|
@@ -14429,11 +14733,11 @@ var prefer_zod_infer_default = createRule({
|
|
|
14429
14733
|
}
|
|
14430
14734
|
return;
|
|
14431
14735
|
}
|
|
14432
|
-
if (node.type ===
|
|
14736
|
+
if (node.type === AST_NODE_TYPES63.TSArrayType) {
|
|
14433
14737
|
collectConstrainedNames(node.elementType);
|
|
14434
14738
|
return;
|
|
14435
14739
|
}
|
|
14436
|
-
if (node.type ===
|
|
14740
|
+
if (node.type === AST_NODE_TYPES63.TSUnionType || node.type === AST_NODE_TYPES63.TSIntersectionType) {
|
|
14437
14741
|
for (const member of node.types) {
|
|
14438
14742
|
collectConstrainedNames(member);
|
|
14439
14743
|
}
|
|
@@ -14477,7 +14781,7 @@ var prefer_zod_infer_default = createRule({
|
|
|
14477
14781
|
return {
|
|
14478
14782
|
Program(node) {
|
|
14479
14783
|
for (const statement of node.body) {
|
|
14480
|
-
if (statement.type ===
|
|
14784
|
+
if (statement.type === AST_NODE_TYPES63.ImportDeclaration) {
|
|
14481
14785
|
recordZodImport(statement);
|
|
14482
14786
|
}
|
|
14483
14787
|
}
|
|
@@ -14486,7 +14790,7 @@ var prefer_zod_infer_default = createRule({
|
|
|
14486
14790
|
recordZodImport(node);
|
|
14487
14791
|
},
|
|
14488
14792
|
VariableDeclarator(node) {
|
|
14489
|
-
if (node.id.type !==
|
|
14793
|
+
if (node.id.type !== AST_NODE_TYPES63.Identifier || node.init == null) {
|
|
14490
14794
|
return;
|
|
14491
14795
|
}
|
|
14492
14796
|
const fields = schemaFields(node.init);
|
|
@@ -14503,14 +14807,14 @@ var prefer_zod_infer_default = createRule({
|
|
|
14503
14807
|
},
|
|
14504
14808
|
/** Records `XSchema.transform(...)` and equivalent module-level reshaping. */
|
|
14505
14809
|
"MemberExpression[computed=false]"(node) {
|
|
14506
|
-
if (node.object.type ===
|
|
14810
|
+
if (node.object.type === AST_NODE_TYPES63.Identifier && node.property.type === AST_NODE_TYPES63.Identifier && MODULE_LEVEL_RESHAPERS.has(node.property.name)) {
|
|
14507
14811
|
reshapedSchemaNames.add(node.object.name);
|
|
14508
14812
|
}
|
|
14509
14813
|
},
|
|
14510
14814
|
/** Records every type argument carried by a Zod constraint. */
|
|
14511
14815
|
TSTypeReference(node) {
|
|
14512
14816
|
const { typeName } = node;
|
|
14513
|
-
const referenced = typeName.type ===
|
|
14817
|
+
const referenced = typeName.type === AST_NODE_TYPES63.Identifier ? typeName.name : typeName.type === AST_NODE_TYPES63.TSQualifiedName && typeName.right.type === AST_NODE_TYPES63.Identifier ? typeName.right.name : null;
|
|
14514
14818
|
if (referenced === null || !ZOD_TYPE_CONSTRAINTS.has(referenced)) {
|
|
14515
14819
|
return;
|
|
14516
14820
|
}
|
|
@@ -14542,7 +14846,7 @@ var prefer_zod_infer_default = createRule({
|
|
|
14542
14846
|
typeName: node.id.name
|
|
14543
14847
|
});
|
|
14544
14848
|
}
|
|
14545
|
-
if (node.typeParameters !== void 0 || node.typeAnnotation.type !==
|
|
14849
|
+
if (node.typeParameters !== void 0 || node.typeAnnotation.type !== AST_NODE_TYPES63.TSTypeLiteral) {
|
|
14546
14850
|
return;
|
|
14547
14851
|
}
|
|
14548
14852
|
const members = typeMembers(node.typeAnnotation.members);
|
|
@@ -14643,7 +14947,7 @@ var prefer_zod_infer_default = createRule({
|
|
|
14643
14947
|
// src/rules/require-assert-never.ts
|
|
14644
14948
|
import {
|
|
14645
14949
|
ESLintUtils as ESLintUtils7,
|
|
14646
|
-
AST_NODE_TYPES as
|
|
14950
|
+
AST_NODE_TYPES as AST_NODE_TYPES64
|
|
14647
14951
|
} from "@typescript-eslint/utils";
|
|
14648
14952
|
import ts5 from "typescript";
|
|
14649
14953
|
var REQUIRE_ASSERT_NEVER_DOCUMENTATION = {
|
|
@@ -14657,14 +14961,14 @@ var REQUIRE_ASSERT_NEVER_DOCUMENTATION = {
|
|
|
14657
14961
|
]
|
|
14658
14962
|
};
|
|
14659
14963
|
var isRuntimeHandlingStatement = (statement) => {
|
|
14660
|
-
if (statement.type ===
|
|
14661
|
-
if (statement.type ===
|
|
14964
|
+
if (statement.type === AST_NODE_TYPES64.EmptyStatement) return false;
|
|
14965
|
+
if (statement.type === AST_NODE_TYPES64.BreakStatement) {
|
|
14662
14966
|
return statement.label !== null;
|
|
14663
14967
|
}
|
|
14664
|
-
if (statement.type ===
|
|
14968
|
+
if (statement.type === AST_NODE_TYPES64.TSTypeAliasDeclaration || statement.type === AST_NODE_TYPES64.TSInterfaceDeclaration) {
|
|
14665
14969
|
return false;
|
|
14666
14970
|
}
|
|
14667
|
-
if (statement.type ===
|
|
14971
|
+
if (statement.type === AST_NODE_TYPES64.BlockStatement) {
|
|
14668
14972
|
return statement.body.some(isRuntimeHandlingStatement);
|
|
14669
14973
|
}
|
|
14670
14974
|
return true;
|
|
@@ -14680,7 +14984,7 @@ var isCommentOnlyNoopDefault = (defaultCase, sourceCode) => {
|
|
|
14680
14984
|
return colonToken !== null && sourceCode.getCommentsAfter(colonToken).length > 0;
|
|
14681
14985
|
}
|
|
14682
14986
|
const only = defaultCase.consequent[0];
|
|
14683
|
-
if (only !== void 0 && defaultCase.consequent.length === 1 && only.type ===
|
|
14987
|
+
if (only !== void 0 && defaultCase.consequent.length === 1 && only.type === AST_NODE_TYPES64.BlockStatement && !only.body.some(isRuntimeHandlingStatement)) {
|
|
14684
14988
|
return sourceCode.getCommentsInside(only).length > 0;
|
|
14685
14989
|
}
|
|
14686
14990
|
return false;
|
|
@@ -14763,7 +15067,7 @@ var require_assert_never_default = createRule({
|
|
|
14763
15067
|
});
|
|
14764
15068
|
|
|
14765
15069
|
// src/rules/require-fetch-timeout.ts
|
|
14766
|
-
import { AST_NODE_TYPES as
|
|
15070
|
+
import { AST_NODE_TYPES as AST_NODE_TYPES65, ASTUtils as ASTUtils19 } from "@typescript-eslint/utils";
|
|
14767
15071
|
var REQUIRE_FETCH_TIMEOUT_DOCUMENTATION = {
|
|
14768
15072
|
summary: "Require an abort `signal` (e.g. `AbortSignal.timeout(ms)`) on global `fetch()` calls so stalled upstreams cannot hang the caller forever.",
|
|
14769
15073
|
rationale: "An unbounded request can occupy work indefinitely when an upstream stalls.",
|
|
@@ -14789,14 +15093,14 @@ function matchesAnyPattern3(filename, patterns) {
|
|
|
14789
15093
|
return false;
|
|
14790
15094
|
}
|
|
14791
15095
|
function initProvablyLacksSignal(init) {
|
|
14792
|
-
if (init.type !==
|
|
15096
|
+
if (init.type !== AST_NODE_TYPES65.ObjectExpression) {
|
|
14793
15097
|
return false;
|
|
14794
15098
|
}
|
|
14795
15099
|
for (const prop of init.properties) {
|
|
14796
|
-
if (prop.type ===
|
|
15100
|
+
if (prop.type === AST_NODE_TYPES65.SpreadElement) {
|
|
14797
15101
|
return false;
|
|
14798
15102
|
}
|
|
14799
|
-
if (prop.key.type ===
|
|
15103
|
+
if (prop.key.type === AST_NODE_TYPES65.Identifier && prop.key.name === "signal" || prop.key.type === AST_NODE_TYPES65.Literal && prop.key.value === "signal") {
|
|
14800
15104
|
return false;
|
|
14801
15105
|
}
|
|
14802
15106
|
if (prop.computed) {
|
|
@@ -14806,7 +15110,7 @@ function initProvablyLacksSignal(init) {
|
|
|
14806
15110
|
return true;
|
|
14807
15111
|
}
|
|
14808
15112
|
function isInlineUrl(node, resolvesToGlobal) {
|
|
14809
|
-
return node.type ===
|
|
15113
|
+
return node.type === AST_NODE_TYPES65.Literal && typeof node.value === "string" || node.type === AST_NODE_TYPES65.TemplateLiteral || node.type === AST_NODE_TYPES65.NewExpression && node.callee.type === AST_NODE_TYPES65.Identifier && node.callee.name === "URL" && resolvesToGlobal(node.callee);
|
|
14810
15114
|
}
|
|
14811
15115
|
var require_fetch_timeout_default = createRule({
|
|
14812
15116
|
name: "require-fetch-timeout",
|
|
@@ -14848,10 +15152,10 @@ var require_fetch_timeout_default = createRule({
|
|
|
14848
15152
|
return variable === null || variable.defs.length === 0;
|
|
14849
15153
|
}
|
|
14850
15154
|
function isGlobalFetchCall2(callee) {
|
|
14851
|
-
if (callee.type ===
|
|
15155
|
+
if (callee.type === AST_NODE_TYPES65.Identifier) {
|
|
14852
15156
|
return callee.name === "fetch" && resolvesToGlobal(callee);
|
|
14853
15157
|
}
|
|
14854
|
-
return callee.type ===
|
|
15158
|
+
return callee.type === AST_NODE_TYPES65.MemberExpression && !callee.computed && callee.property.type === AST_NODE_TYPES65.Identifier && callee.property.name === "fetch" && callee.object.type === AST_NODE_TYPES65.Identifier && GLOBAL_OBJECTS2.has(callee.object.name) && resolvesToGlobal(callee.object);
|
|
14855
15159
|
}
|
|
14856
15160
|
function localConstInitProvablyLacksSignal(identifier) {
|
|
14857
15161
|
const variable = ASTUtils19.findVariable(
|
|
@@ -14860,14 +15164,14 @@ var require_fetch_timeout_default = createRule({
|
|
|
14860
15164
|
);
|
|
14861
15165
|
if (variable?.defs.length !== 1) return false;
|
|
14862
15166
|
const definition = variable.defs[0];
|
|
14863
|
-
if (definition?.type !== "Variable" || definition.parent.kind !== "const" || definition.node.init?.type !==
|
|
15167
|
+
if (definition?.type !== "Variable" || definition.parent.kind !== "const" || definition.node.init?.type !== AST_NODE_TYPES65.ObjectExpression || !initProvablyLacksSignal(definition.node.init)) {
|
|
14864
15168
|
return false;
|
|
14865
15169
|
}
|
|
14866
15170
|
for (const reference of variable.references) {
|
|
14867
15171
|
const ref = reference.identifier;
|
|
14868
15172
|
if (ref === identifier || ref === definition.name) continue;
|
|
14869
15173
|
const member = ref.parent;
|
|
14870
|
-
if (member.type !==
|
|
15174
|
+
if (member.type !== AST_NODE_TYPES65.MemberExpression || member.object !== ref || member.computed || member.property.type !== AST_NODE_TYPES65.Identifier || member.property.name === "signal" || member.parent.type !== AST_NODE_TYPES65.AssignmentExpression || member.parent.left !== member) {
|
|
14871
15175
|
return false;
|
|
14872
15176
|
}
|
|
14873
15177
|
}
|
|
@@ -14882,7 +15186,7 @@ var require_fetch_timeout_default = createRule({
|
|
|
14882
15186
|
if (node.arguments.length === 1 && first !== void 0 && !isInlineUrl(first, resolvesToGlobal)) {
|
|
14883
15187
|
return;
|
|
14884
15188
|
}
|
|
14885
|
-
if (init === void 0 || initProvablyLacksSignal(init) || init.type ===
|
|
15189
|
+
if (init === void 0 || initProvablyLacksSignal(init) || init.type === AST_NODE_TYPES65.Identifier && localConstInitProvablyLacksSignal(init)) {
|
|
14886
15190
|
context.report({ node, messageId: "missingSignal" });
|
|
14887
15191
|
}
|
|
14888
15192
|
}
|
|
@@ -14891,7 +15195,7 @@ var require_fetch_timeout_default = createRule({
|
|
|
14891
15195
|
});
|
|
14892
15196
|
|
|
14893
15197
|
// src/rules/require-port-for-service.ts
|
|
14894
|
-
import { AST_NODE_TYPES as
|
|
15198
|
+
import { AST_NODE_TYPES as AST_NODE_TYPES66 } from "@typescript-eslint/utils";
|
|
14895
15199
|
var REQUIRE_PORT_FOR_SERVICE_DOCUMENTATION = {
|
|
14896
15200
|
summary: "Advise when an exported service with injected collaborators has public methods not covered by its declared ports.",
|
|
14897
15201
|
rationale: "A declared port keeps consumers coupled to the service capability instead of its concrete implementation.",
|
|
@@ -14916,45 +15220,45 @@ var ROUTER_FACTORY_NAME = "Router";
|
|
|
14916
15220
|
var FRAMEWORK_HTTP_TYPES = /* @__PURE__ */ new Set(["Request", "Response", "NextFunction"]);
|
|
14917
15221
|
var STORAGE_ASSIGNMENT_OPERATORS = /* @__PURE__ */ new Set(["=", "&&=", "??=", "||="]);
|
|
14918
15222
|
var staticMemberName6 = (member) => {
|
|
14919
|
-
if (member.property.type ===
|
|
14920
|
-
if (!member.computed && member.property.type ===
|
|
14921
|
-
return member.computed && member.property.type ===
|
|
15223
|
+
if (member.property.type === AST_NODE_TYPES66.PrivateIdentifier) return `#${member.property.name}`;
|
|
15224
|
+
if (!member.computed && member.property.type === AST_NODE_TYPES66.Identifier) return member.property.name;
|
|
15225
|
+
return member.computed && member.property.type === AST_NODE_TYPES66.Literal && typeof member.property.value === "string" ? member.property.value : null;
|
|
14922
15226
|
};
|
|
14923
15227
|
var detachedValueExports = (program) => {
|
|
14924
15228
|
const names = /* @__PURE__ */ new Set();
|
|
14925
15229
|
for (const statement of program.body) {
|
|
14926
|
-
if (statement.type ===
|
|
15230
|
+
if (statement.type === AST_NODE_TYPES66.ExportNamedDeclaration && statement.declaration === null && statement.source === null && statement.exportKind !== "type") {
|
|
14927
15231
|
for (const specifier of statement.specifiers) {
|
|
14928
15232
|
if (specifier.exportKind !== "type") names.add(specifier.local.name);
|
|
14929
15233
|
}
|
|
14930
|
-
} else if (statement.type ===
|
|
15234
|
+
} else if (statement.type === AST_NODE_TYPES66.ExportDefaultDeclaration && statement.declaration.type === AST_NODE_TYPES66.Identifier) {
|
|
14931
15235
|
names.add(statement.declaration.name);
|
|
14932
|
-
} else if (statement.type ===
|
|
15236
|
+
} else if (statement.type === AST_NODE_TYPES66.TSExportAssignment && statement.expression.type === AST_NODE_TYPES66.Identifier) {
|
|
14933
15237
|
names.add(statement.expression.name);
|
|
14934
15238
|
}
|
|
14935
15239
|
}
|
|
14936
15240
|
return names;
|
|
14937
15241
|
};
|
|
14938
|
-
var isExportedClass2 = (node, detached) => node.parent.type ===
|
|
15242
|
+
var isExportedClass2 = (node, detached) => node.parent.type === AST_NODE_TYPES66.ExportNamedDeclaration || node.parent.type === AST_NODE_TYPES66.ExportDefaultDeclaration || node.id !== null && detached.has(node.id.name);
|
|
14939
15243
|
var readTypeReference = (annotation) => {
|
|
14940
|
-
if (annotation?.type ===
|
|
15244
|
+
if (annotation?.type === AST_NODE_TYPES66.TSUnionType) {
|
|
14941
15245
|
const members = annotation.types.filter(
|
|
14942
|
-
(member) => member.type !==
|
|
15246
|
+
(member) => member.type !== AST_NODE_TYPES66.TSUndefinedKeyword && member.type !== AST_NODE_TYPES66.TSNullKeyword
|
|
14943
15247
|
);
|
|
14944
15248
|
annotation = members.length === 1 ? members[0] : void 0;
|
|
14945
15249
|
}
|
|
14946
|
-
if (annotation === void 0 || annotation.type !==
|
|
15250
|
+
if (annotation === void 0 || annotation.type !== AST_NODE_TYPES66.TSTypeReference) return null;
|
|
14947
15251
|
const { typeName } = annotation;
|
|
14948
|
-
const rightmost = typeName.type ===
|
|
15252
|
+
const rightmost = typeName.type === AST_NODE_TYPES66.Identifier ? typeName.name : typeName.type === AST_NODE_TYPES66.TSQualifiedName ? typeName.right.name : null;
|
|
14949
15253
|
if (rightmost === null) return null;
|
|
14950
15254
|
return { typeName: rightmost, display: qualifiedName(typeName) };
|
|
14951
15255
|
};
|
|
14952
|
-
var qualifiedName = (name) => name.type ===
|
|
15256
|
+
var qualifiedName = (name) => name.type === AST_NODE_TYPES66.Identifier ? name.name : name.type === AST_NODE_TYPES66.TSQualifiedName ? `${qualifiedName(name.left)}.${name.right.name}` : "";
|
|
14953
15257
|
var propertySignatureTypes = (members) => {
|
|
14954
15258
|
const types = /* @__PURE__ */ new Map();
|
|
14955
15259
|
for (const member of members) {
|
|
14956
|
-
if (member.type !==
|
|
14957
|
-
if (member.computed || member.key.type !==
|
|
15260
|
+
if (member.type !== AST_NODE_TYPES66.TSPropertySignature) continue;
|
|
15261
|
+
if (member.computed || member.key.type !== AST_NODE_TYPES66.Identifier) continue;
|
|
14958
15262
|
const reference = readTypeReference(member.typeAnnotation?.typeAnnotation);
|
|
14959
15263
|
if (reference === null) continue;
|
|
14960
15264
|
types.set(member.key.name, reference);
|
|
@@ -14965,18 +15269,18 @@ var fileTypeIndex = (program) => {
|
|
|
14965
15269
|
const objects = /* @__PURE__ */ new Map();
|
|
14966
15270
|
const functionAliases = /* @__PURE__ */ new Set();
|
|
14967
15271
|
for (const statement of program.body) {
|
|
14968
|
-
const declaration = statement.type ===
|
|
14969
|
-
if (declaration?.type ===
|
|
15272
|
+
const declaration = statement.type === AST_NODE_TYPES66.ExportNamedDeclaration ? statement.declaration : statement;
|
|
15273
|
+
if (declaration?.type === AST_NODE_TYPES66.TSInterfaceDeclaration) {
|
|
14970
15274
|
objects.set(declaration.id.name, propertySignatureTypes(declaration.body.body));
|
|
14971
15275
|
continue;
|
|
14972
15276
|
}
|
|
14973
|
-
if (declaration?.type !==
|
|
15277
|
+
if (declaration?.type !== AST_NODE_TYPES66.TSTypeAliasDeclaration) continue;
|
|
14974
15278
|
const aliased = declaration.typeAnnotation;
|
|
14975
|
-
if (aliased.type ===
|
|
15279
|
+
if (aliased.type === AST_NODE_TYPES66.TSFunctionType || aliased.type === AST_NODE_TYPES66.TSConstructorType) {
|
|
14976
15280
|
functionAliases.add(declaration.id.name);
|
|
14977
15281
|
continue;
|
|
14978
15282
|
}
|
|
14979
|
-
const literals = aliased.type ===
|
|
15283
|
+
const literals = aliased.type === AST_NODE_TYPES66.TSTypeLiteral ? [aliased] : aliased.type === AST_NODE_TYPES66.TSIntersectionType ? aliased.types.filter((part) => part.type === AST_NODE_TYPES66.TSTypeLiteral) : [];
|
|
14980
15284
|
if (literals.length === 0) continue;
|
|
14981
15285
|
const merged = /* @__PURE__ */ new Map();
|
|
14982
15286
|
for (const literal of literals) {
|
|
@@ -15005,10 +15309,10 @@ var readConstructor = (ctor, declared, typeParameters) => {
|
|
|
15005
15309
|
while (pending.length > 0) {
|
|
15006
15310
|
const current = pending.pop();
|
|
15007
15311
|
if (current === void 0) break;
|
|
15008
|
-
if (current.type ===
|
|
15009
|
-
const expression = current.type ===
|
|
15010
|
-
const storedField = expression?.type ===
|
|
15011
|
-
if (expression?.type !==
|
|
15312
|
+
if (current.type === AST_NODE_TYPES66.ArrowFunctionExpression || current.type === AST_NODE_TYPES66.FunctionExpression || current.type === AST_NODE_TYPES66.FunctionDeclaration || current.type === AST_NODE_TYPES66.ClassExpression || current.type === AST_NODE_TYPES66.ClassDeclaration) continue;
|
|
15313
|
+
const expression = current.type === AST_NODE_TYPES66.ExpressionStatement ? current.expression : null;
|
|
15314
|
+
const storedField = expression?.type === AST_NODE_TYPES66.AssignmentExpression && expression.left.type === AST_NODE_TYPES66.MemberExpression && expression.left.object.type === AST_NODE_TYPES66.ThisExpression ? staticMemberName6(expression.left) : null;
|
|
15315
|
+
if (expression?.type !== AST_NODE_TYPES66.AssignmentExpression || !STORAGE_ASSIGNMENT_OPERATORS.has(expression.operator) || expression.left.type !== AST_NODE_TYPES66.MemberExpression || expression.left.object.type !== AST_NODE_TYPES66.ThisExpression || storedField === null) {
|
|
15012
15316
|
for (const key of Object.keys(current)) {
|
|
15013
15317
|
if (key === "parent") continue;
|
|
15014
15318
|
const value = current[key];
|
|
@@ -15021,14 +15325,14 @@ var readConstructor = (ctor, declared, typeParameters) => {
|
|
|
15021
15325
|
continue;
|
|
15022
15326
|
}
|
|
15023
15327
|
let source = expression.right;
|
|
15024
|
-
while (source.type ===
|
|
15025
|
-
if (source.type ===
|
|
15328
|
+
while (source.type === AST_NODE_TYPES66.TSNonNullExpression || source.type === AST_NODE_TYPES66.TSAsExpression || source.type === AST_NODE_TYPES66.TSSatisfiesExpression || source.type === AST_NODE_TYPES66.TSTypeAssertion) source = source.expression;
|
|
15329
|
+
if (source.type === AST_NODE_TYPES66.NewExpression) {
|
|
15026
15330
|
constructedFields += 1;
|
|
15027
|
-
} else if (source.type ===
|
|
15331
|
+
} else if (source.type === AST_NODE_TYPES66.Identifier) {
|
|
15028
15332
|
const fields = storedFieldsFrom.get(source.name) ?? /* @__PURE__ */ new Set();
|
|
15029
15333
|
fields.add(storedField);
|
|
15030
15334
|
storedFieldsFrom.set(source.name, fields);
|
|
15031
|
-
} else if (source.type ===
|
|
15335
|
+
} else if (source.type === AST_NODE_TYPES66.MemberExpression && source.object.type === AST_NODE_TYPES66.Identifier) {
|
|
15032
15336
|
const fields = storedFieldsFrom.get(source.object.name) ?? /* @__PURE__ */ new Set();
|
|
15033
15337
|
fields.add(storedField);
|
|
15034
15338
|
storedFieldsFrom.set(source.object.name, fields);
|
|
@@ -15046,7 +15350,7 @@ var readConstructor = (ctor, declared, typeParameters) => {
|
|
|
15046
15350
|
const collaborators = [];
|
|
15047
15351
|
for (const parameter of ctor.value.params) {
|
|
15048
15352
|
for (const reference of parameterCollaborators(parameter, declared, storedMemberFieldsFrom)) {
|
|
15049
|
-
const fields = parameter.type ===
|
|
15353
|
+
const fields = parameter.type === AST_NODE_TYPES66.TSParameterProperty ? [reference.name] : reference.fields.length > 0 ? reference.fields : [...storedFieldsFrom.get(reference.name) ?? []];
|
|
15050
15354
|
if (fields.length === 0) continue;
|
|
15051
15355
|
if (CONFIGISH_TYPE_RE.test(reference.typeName)) continue;
|
|
15052
15356
|
if (CONFIGISH_NAME_RE.test(reference.name)) continue;
|
|
@@ -15061,8 +15365,8 @@ var readConstructor = (ctor, declared, typeParameters) => {
|
|
|
15061
15365
|
};
|
|
15062
15366
|
var parameterCollaborators = (parameter, declared, storedMemberFieldsFrom) => {
|
|
15063
15367
|
let target = parameter;
|
|
15064
|
-
if (target.type ===
|
|
15065
|
-
if (target.type ===
|
|
15368
|
+
if (target.type === AST_NODE_TYPES66.AssignmentPattern) target = target.left;
|
|
15369
|
+
if (target.type === AST_NODE_TYPES66.ObjectPattern) {
|
|
15066
15370
|
return objectPatternCollaborators(target, declared);
|
|
15067
15371
|
}
|
|
15068
15372
|
const named2 = namedParameterCollaborator(parameter);
|
|
@@ -15071,9 +15375,9 @@ var parameterCollaborators = (parameter, declared, storedMemberFieldsFrom) => {
|
|
|
15071
15375
|
};
|
|
15072
15376
|
var namedBagCollaborators = (annotated, declared, storedMemberFieldsFrom) => {
|
|
15073
15377
|
let target = annotated;
|
|
15074
|
-
if (target.type ===
|
|
15075
|
-
if (target.type ===
|
|
15076
|
-
if (target.type !==
|
|
15378
|
+
if (target.type === AST_NODE_TYPES66.TSParameterProperty) target = target.parameter;
|
|
15379
|
+
if (target.type === AST_NODE_TYPES66.AssignmentPattern) target = target.left;
|
|
15380
|
+
if (target.type !== AST_NODE_TYPES66.Identifier) return [];
|
|
15077
15381
|
const members = bagMemberTypes(target.typeAnnotation?.typeAnnotation, declared);
|
|
15078
15382
|
if (members === null) return [];
|
|
15079
15383
|
const storedMembers = storedMemberFieldsFrom.get(target.name);
|
|
@@ -15089,9 +15393,9 @@ var namedBagCollaborators = (annotated, declared, storedMemberFieldsFrom) => {
|
|
|
15089
15393
|
};
|
|
15090
15394
|
var namedParameterCollaborator = (annotated) => {
|
|
15091
15395
|
let target = annotated;
|
|
15092
|
-
if (target.type ===
|
|
15093
|
-
if (target.type ===
|
|
15094
|
-
if (target.type !==
|
|
15396
|
+
if (target.type === AST_NODE_TYPES66.TSParameterProperty) target = target.parameter;
|
|
15397
|
+
if (target.type === AST_NODE_TYPES66.AssignmentPattern) target = target.left;
|
|
15398
|
+
if (target.type !== AST_NODE_TYPES66.Identifier) return null;
|
|
15095
15399
|
const reference = readTypeReference(target.typeAnnotation?.typeAnnotation);
|
|
15096
15400
|
if (reference === null) return null;
|
|
15097
15401
|
return { name: target.name, ...reference, fields: [] };
|
|
@@ -15103,11 +15407,11 @@ var objectPatternCollaborators = (pattern, declared) => {
|
|
|
15103
15407
|
if (members === null) return [];
|
|
15104
15408
|
const collaborators = [];
|
|
15105
15409
|
for (const property of pattern.properties) {
|
|
15106
|
-
if (property.type !==
|
|
15107
|
-
if (property.key.type !==
|
|
15410
|
+
if (property.type !== AST_NODE_TYPES66.Property || property.computed) continue;
|
|
15411
|
+
if (property.key.type !== AST_NODE_TYPES66.Identifier) continue;
|
|
15108
15412
|
const key = property.key.name;
|
|
15109
|
-
const bound = property.value.type ===
|
|
15110
|
-
if (bound.type !==
|
|
15413
|
+
const bound = property.value.type === AST_NODE_TYPES66.AssignmentPattern ? property.value.left : property.value;
|
|
15414
|
+
if (bound.type !== AST_NODE_TYPES66.Identifier) continue;
|
|
15111
15415
|
if (CONFIGISH_NAME_RE.test(key)) continue;
|
|
15112
15416
|
const reference = members.get(key);
|
|
15113
15417
|
if (reference === void 0) continue;
|
|
@@ -15117,21 +15421,21 @@ var objectPatternCollaborators = (pattern, declared) => {
|
|
|
15117
15421
|
};
|
|
15118
15422
|
var bagMemberTypes = (annotation, declared) => {
|
|
15119
15423
|
if (annotation === void 0) return null;
|
|
15120
|
-
if (annotation.type ===
|
|
15424
|
+
if (annotation.type === AST_NODE_TYPES66.TSTypeLiteral) {
|
|
15121
15425
|
return propertySignatureTypes(annotation.members);
|
|
15122
15426
|
}
|
|
15123
|
-
if (annotation.type !==
|
|
15427
|
+
if (annotation.type !== AST_NODE_TYPES66.TSTypeReference || annotation.typeName.type !== AST_NODE_TYPES66.Identifier) {
|
|
15124
15428
|
return null;
|
|
15125
15429
|
}
|
|
15126
15430
|
return declared().objects.get(annotation.typeName.name) ?? null;
|
|
15127
15431
|
};
|
|
15128
15432
|
var isFrameworkWiring = (body2) => subtreeHas(body2, (node) => {
|
|
15129
|
-
if (node.type ===
|
|
15433
|
+
if (node.type === AST_NODE_TYPES66.CallExpression) {
|
|
15130
15434
|
const { callee } = node;
|
|
15131
|
-
if (callee.type ===
|
|
15132
|
-
return callee.type ===
|
|
15435
|
+
if (callee.type === AST_NODE_TYPES66.Identifier) return callee.name === ROUTER_FACTORY_NAME;
|
|
15436
|
+
return callee.type === AST_NODE_TYPES66.MemberExpression && !callee.computed && callee.property.type === AST_NODE_TYPES66.Identifier && callee.property.name === ROUTER_FACTORY_NAME;
|
|
15133
15437
|
}
|
|
15134
|
-
return node.type ===
|
|
15438
|
+
return node.type === AST_NODE_TYPES66.TSTypeReference && node.typeName.type === AST_NODE_TYPES66.TSQualifiedName && FRAMEWORK_HTTP_TYPES.has(node.typeName.right.name);
|
|
15135
15439
|
});
|
|
15136
15440
|
var subtreeHas = (root, found) => {
|
|
15137
15441
|
let hit = false;
|
|
@@ -15158,19 +15462,19 @@ var invokedInstanceField = (call) => {
|
|
|
15158
15462
|
const direct = instanceField(call.callee);
|
|
15159
15463
|
if (direct !== null) return direct;
|
|
15160
15464
|
let callee = call.callee;
|
|
15161
|
-
while (callee.type ===
|
|
15162
|
-
return callee.type ===
|
|
15465
|
+
while (callee.type === AST_NODE_TYPES66.ChainExpression || callee.type === AST_NODE_TYPES66.TSAsExpression || callee.type === AST_NODE_TYPES66.TSNonNullExpression || callee.type === AST_NODE_TYPES66.TSSatisfiesExpression || callee.type === AST_NODE_TYPES66.TSTypeAssertion) callee = callee.expression;
|
|
15466
|
+
return callee.type === AST_NODE_TYPES66.MemberExpression ? instanceField(callee.object) : null;
|
|
15163
15467
|
};
|
|
15164
15468
|
var instanceField = (candidate2) => {
|
|
15165
15469
|
let node = candidate2;
|
|
15166
|
-
while (node.type ===
|
|
15167
|
-
return node.type ===
|
|
15470
|
+
while (node.type === AST_NODE_TYPES66.ChainExpression || node.type === AST_NODE_TYPES66.TSAsExpression || node.type === AST_NODE_TYPES66.TSNonNullExpression || node.type === AST_NODE_TYPES66.TSSatisfiesExpression || node.type === AST_NODE_TYPES66.TSTypeAssertion) node = node.expression;
|
|
15471
|
+
return node.type === AST_NODE_TYPES66.MemberExpression && node.object.type === AST_NODE_TYPES66.ThisExpression ? staticMemberName6(node) : null;
|
|
15168
15472
|
};
|
|
15169
15473
|
var behaviorallyInvokedFields = (body2) => {
|
|
15170
15474
|
const invoked = /* @__PURE__ */ new Set();
|
|
15171
15475
|
const visit = (current) => {
|
|
15172
|
-
if (current.type ===
|
|
15173
|
-
if (current.type ===
|
|
15476
|
+
if (current.type === AST_NODE_TYPES66.ClassDeclaration || current.type === AST_NODE_TYPES66.ClassExpression || current.type === AST_NODE_TYPES66.FunctionDeclaration || current.type === AST_NODE_TYPES66.FunctionExpression) return;
|
|
15477
|
+
if (current.type === AST_NODE_TYPES66.CallExpression) {
|
|
15174
15478
|
const field = invokedInstanceField(current);
|
|
15175
15479
|
if (field !== null) invoked.add(field);
|
|
15176
15480
|
}
|
|
@@ -15183,14 +15487,14 @@ var behaviorallyInvokedFields = (body2) => {
|
|
|
15183
15487
|
}
|
|
15184
15488
|
};
|
|
15185
15489
|
for (const member of body2.body) {
|
|
15186
|
-
if (member.type ===
|
|
15187
|
-
if (member.type ===
|
|
15490
|
+
if (member.type === AST_NODE_TYPES66.StaticBlock || member.static) continue;
|
|
15491
|
+
if (member.type === AST_NODE_TYPES66.MethodDefinition) {
|
|
15188
15492
|
if (member.value.body !== null && member.value.body !== void 0) visit(member.value.body);
|
|
15189
15493
|
continue;
|
|
15190
15494
|
}
|
|
15191
|
-
if (member.type !==
|
|
15495
|
+
if (member.type !== AST_NODE_TYPES66.PropertyDefinition || member.value === null) continue;
|
|
15192
15496
|
visit(
|
|
15193
|
-
member.value.type ===
|
|
15497
|
+
member.value.type === AST_NODE_TYPES66.ArrowFunctionExpression ? member.value.body : member.value
|
|
15194
15498
|
);
|
|
15195
15499
|
}
|
|
15196
15500
|
return invoked;
|
|
@@ -15210,25 +15514,26 @@ var isTransportWrapper = (className, collaborators, program) => {
|
|
|
15210
15514
|
var fileInterfaceNames = (program) => {
|
|
15211
15515
|
const names = [];
|
|
15212
15516
|
for (const statement of program.body) {
|
|
15213
|
-
const declaration = statement.type ===
|
|
15214
|
-
if (declaration?.type ===
|
|
15517
|
+
const declaration = statement.type === AST_NODE_TYPES66.ExportNamedDeclaration ? statement.declaration : statement;
|
|
15518
|
+
if (declaration?.type === AST_NODE_TYPES66.TSInterfaceDeclaration) names.push(declaration.id.name);
|
|
15215
15519
|
}
|
|
15216
15520
|
return names;
|
|
15217
15521
|
};
|
|
15218
15522
|
var publicMethodNames = (body2, functionAliases) => {
|
|
15219
15523
|
const names = [];
|
|
15220
15524
|
for (const member of body2.body) {
|
|
15221
|
-
if (member.type ===
|
|
15525
|
+
if (member.type === AST_NODE_TYPES66.PropertyDefinition) {
|
|
15222
15526
|
if (member.static || member.accessibility === "private" || member.accessibility === "protected") continue;
|
|
15223
|
-
if (member.
|
|
15224
|
-
|
|
15527
|
+
if (member.key.type === AST_NODE_TYPES66.PrivateIdentifier) continue;
|
|
15528
|
+
if (member.value?.type !== AST_NODE_TYPES66.ArrowFunctionExpression && member.value?.type !== AST_NODE_TYPES66.FunctionExpression && member.typeAnnotation?.typeAnnotation.type !== AST_NODE_TYPES66.TSFunctionType && !(member.typeAnnotation?.typeAnnotation.type === AST_NODE_TYPES66.TSTypeReference && member.typeAnnotation.typeAnnotation.typeName.type === AST_NODE_TYPES66.Identifier && functionAliases.has(member.typeAnnotation.typeAnnotation.typeName.name))) continue;
|
|
15529
|
+
names.push(member.key.type === AST_NODE_TYPES66.Identifier ? member.key.name : "\u2026");
|
|
15225
15530
|
continue;
|
|
15226
15531
|
}
|
|
15227
|
-
if (member.type !==
|
|
15532
|
+
if (member.type !== AST_NODE_TYPES66.MethodDefinition) continue;
|
|
15228
15533
|
if (member.kind !== "method" || member.static) continue;
|
|
15229
15534
|
if (member.accessibility === "private" || member.accessibility === "protected") continue;
|
|
15230
|
-
if (member.key.type ===
|
|
15231
|
-
if (member.key.type ===
|
|
15535
|
+
if (member.key.type === AST_NODE_TYPES66.PrivateIdentifier) continue;
|
|
15536
|
+
if (member.key.type === AST_NODE_TYPES66.Identifier) names.push(member.key.name);
|
|
15232
15537
|
else names.push("\u2026");
|
|
15233
15538
|
}
|
|
15234
15539
|
return names;
|
|
@@ -15236,13 +15541,13 @@ var publicMethodNames = (body2, functionAliases) => {
|
|
|
15236
15541
|
var isFluentConstructionObject = (node, getText) => {
|
|
15237
15542
|
if (node.id === null) return false;
|
|
15238
15543
|
const methods = node.body.body.filter(
|
|
15239
|
-
(member) => member.type ===
|
|
15544
|
+
(member) => member.type === AST_NODE_TYPES66.MethodDefinition && member.kind === "method" && !member.static && member.accessibility !== "private" && member.accessibility !== "protected" && member.value.body !== null
|
|
15240
15545
|
);
|
|
15241
15546
|
if (methods.length === 0) return false;
|
|
15242
15547
|
return methods.every((member) => {
|
|
15243
15548
|
const result = member.value.returnType?.typeAnnotation;
|
|
15244
15549
|
if (result === void 0) return false;
|
|
15245
|
-
const returnsOwnType = result.type ===
|
|
15550
|
+
const returnsOwnType = result.type === AST_NODE_TYPES66.TSTypeReference && result.typeName.type === AST_NODE_TYPES66.Identifier && result.typeName.name === node.id?.name;
|
|
15246
15551
|
return returnsOwnType || FLUENT_BUILDER_NAME_RE.test(node.id?.name ?? "") && FLUENT_RESULT_TYPE_RE.test(getText(result));
|
|
15247
15552
|
});
|
|
15248
15553
|
};
|
|
@@ -15250,10 +15555,10 @@ function localClassAbstractness(program) {
|
|
|
15250
15555
|
const classes = /* @__PURE__ */ new Map();
|
|
15251
15556
|
const parents = /* @__PURE__ */ new Map();
|
|
15252
15557
|
for (const statement of program.body) {
|
|
15253
|
-
const declaration = statement.type ===
|
|
15254
|
-
if (declaration?.type ===
|
|
15558
|
+
const declaration = statement.type === AST_NODE_TYPES66.ExportNamedDeclaration || statement.type === AST_NODE_TYPES66.ExportDefaultDeclaration ? statement.declaration : statement;
|
|
15559
|
+
if (declaration?.type === AST_NODE_TYPES66.ClassDeclaration && declaration.id !== null) {
|
|
15255
15560
|
classes.set(declaration.id.name, declaration.abstract === true);
|
|
15256
|
-
if (declaration.superClass?.type ===
|
|
15561
|
+
if (declaration.superClass?.type === AST_NODE_TYPES66.Identifier) {
|
|
15257
15562
|
parents.set(declaration.id.name, declaration.superClass.name);
|
|
15258
15563
|
}
|
|
15259
15564
|
}
|
|
@@ -15275,43 +15580,43 @@ function localInterfaceSurfaces(program) {
|
|
|
15275
15580
|
const parents = /* @__PURE__ */ new Map();
|
|
15276
15581
|
const functionAliases = /* @__PURE__ */ new Set();
|
|
15277
15582
|
for (const statement of program.body) {
|
|
15278
|
-
const declaration = statement.type ===
|
|
15279
|
-
if (declaration?.type ===
|
|
15583
|
+
const declaration = statement.type === AST_NODE_TYPES66.ExportNamedDeclaration ? statement.declaration : statement;
|
|
15584
|
+
if (declaration?.type === AST_NODE_TYPES66.TSTypeAliasDeclaration && (declaration.typeAnnotation.type === AST_NODE_TYPES66.TSFunctionType || declaration.typeAnnotation.type === AST_NODE_TYPES66.TSConstructorType)) functionAliases.add(declaration.id.name);
|
|
15280
15585
|
}
|
|
15281
15586
|
for (const statement of program.body) {
|
|
15282
|
-
const declaration = statement.type ===
|
|
15283
|
-
if (declaration?.type ===
|
|
15587
|
+
const declaration = statement.type === AST_NODE_TYPES66.ExportNamedDeclaration ? statement.declaration : statement;
|
|
15588
|
+
if (declaration?.type === AST_NODE_TYPES66.TSTypeAliasDeclaration) {
|
|
15284
15589
|
const callables2 = interfaces.get(declaration.id.name) ?? /* @__PURE__ */ new Set();
|
|
15285
|
-
const parts = declaration.typeAnnotation.type ===
|
|
15590
|
+
const parts = declaration.typeAnnotation.type === AST_NODE_TYPES66.TSIntersectionType ? declaration.typeAnnotation.types : [declaration.typeAnnotation];
|
|
15286
15591
|
const inherited = parents.get(declaration.id.name) ?? [];
|
|
15287
15592
|
for (const part of parts) {
|
|
15288
|
-
if (part.type ===
|
|
15593
|
+
if (part.type === AST_NODE_TYPES66.TSTypeReference && part.typeName.type === AST_NODE_TYPES66.Identifier) {
|
|
15289
15594
|
inherited.push(part.typeName.name);
|
|
15290
15595
|
continue;
|
|
15291
15596
|
}
|
|
15292
|
-
if (part.type !==
|
|
15597
|
+
if (part.type !== AST_NODE_TYPES66.TSTypeLiteral) continue;
|
|
15293
15598
|
for (const member of part.members) {
|
|
15294
|
-
if (member.type !==
|
|
15295
|
-
if (member.computed || member.key.type !==
|
|
15296
|
-
if (member.type ===
|
|
15599
|
+
if (member.type !== AST_NODE_TYPES66.TSMethodSignature && member.type !== AST_NODE_TYPES66.TSPropertySignature) continue;
|
|
15600
|
+
if (member.computed || member.key.type !== AST_NODE_TYPES66.Identifier) continue;
|
|
15601
|
+
if (member.type === AST_NODE_TYPES66.TSMethodSignature) {
|
|
15297
15602
|
callables2.add(member.key.name);
|
|
15298
15603
|
continue;
|
|
15299
15604
|
}
|
|
15300
|
-
if (member.type !==
|
|
15605
|
+
if (member.type !== AST_NODE_TYPES66.TSPropertySignature) continue;
|
|
15301
15606
|
const annotation = member.typeAnnotation?.typeAnnotation;
|
|
15302
|
-
if (annotation?.type ===
|
|
15607
|
+
if (annotation?.type === AST_NODE_TYPES66.TSFunctionType || annotation?.type === AST_NODE_TYPES66.TSTypeReference && annotation.typeName.type === AST_NODE_TYPES66.Identifier && functionAliases.has(annotation.typeName.name)) callables2.add(member.key.name);
|
|
15303
15608
|
}
|
|
15304
15609
|
}
|
|
15305
15610
|
interfaces.set(declaration.id.name, callables2);
|
|
15306
15611
|
parents.set(declaration.id.name, inherited);
|
|
15307
15612
|
continue;
|
|
15308
15613
|
}
|
|
15309
|
-
if (declaration?.type !==
|
|
15614
|
+
if (declaration?.type !== AST_NODE_TYPES66.TSInterfaceDeclaration) continue;
|
|
15310
15615
|
const callables = interfaces.get(declaration.id.name) ?? /* @__PURE__ */ new Set();
|
|
15311
15616
|
for (const member of declaration.body.body) {
|
|
15312
|
-
if (member.type !==
|
|
15313
|
-
if (member.computed || member.key.type !==
|
|
15314
|
-
if (member.type ===
|
|
15617
|
+
if (member.type !== AST_NODE_TYPES66.TSMethodSignature && member.type !== AST_NODE_TYPES66.TSPropertySignature) continue;
|
|
15618
|
+
if (member.computed || member.key.type !== AST_NODE_TYPES66.Identifier) continue;
|
|
15619
|
+
if (member.type === AST_NODE_TYPES66.TSMethodSignature || member.typeAnnotation?.typeAnnotation.type === AST_NODE_TYPES66.TSFunctionType || member.typeAnnotation?.typeAnnotation.type === AST_NODE_TYPES66.TSTypeReference && member.typeAnnotation.typeAnnotation.typeName.type === AST_NODE_TYPES66.Identifier && functionAliases.has(member.typeAnnotation.typeAnnotation.typeName.name)) callables.add(member.key.name);
|
|
15315
15620
|
}
|
|
15316
15621
|
interfaces.set(declaration.id.name, callables);
|
|
15317
15622
|
parents.set(
|
|
@@ -15319,7 +15624,7 @@ function localInterfaceSurfaces(program) {
|
|
|
15319
15624
|
[
|
|
15320
15625
|
...parents.get(declaration.id.name) ?? [],
|
|
15321
15626
|
...declaration.extends.flatMap(
|
|
15322
|
-
(heritage) => heritage.expression.type ===
|
|
15627
|
+
(heritage) => heritage.expression.type === AST_NODE_TYPES66.Identifier ? [heritage.expression.name] : ["*"]
|
|
15323
15628
|
)
|
|
15324
15629
|
]
|
|
15325
15630
|
);
|
|
@@ -15346,7 +15651,7 @@ function localInterfaceSurfaces(program) {
|
|
|
15346
15651
|
}
|
|
15347
15652
|
function hasServicePort(node, methods, classes, interfaces) {
|
|
15348
15653
|
if (node.superClass !== null) {
|
|
15349
|
-
if (node.superClass.type !==
|
|
15654
|
+
if (node.superClass.type !== AST_NODE_TYPES66.Identifier) return true;
|
|
15350
15655
|
const localAbstract = classes.get(node.superClass.name);
|
|
15351
15656
|
if (localAbstract === void 0 || localAbstract) return true;
|
|
15352
15657
|
}
|
|
@@ -15358,7 +15663,7 @@ function hasServicePort(node, methods, classes, interfaces) {
|
|
|
15358
15663
|
if (node.implements.length === 0) return false;
|
|
15359
15664
|
const combined = /* @__PURE__ */ new Set();
|
|
15360
15665
|
for (const implementation of node.implements) {
|
|
15361
|
-
if (implementation.expression.type !==
|
|
15666
|
+
if (implementation.expression.type !== AST_NODE_TYPES66.Identifier) return true;
|
|
15362
15667
|
const name = implementation.expression.name;
|
|
15363
15668
|
const localAbstract = classes.get(name);
|
|
15364
15669
|
if (localAbstract === true) return true;
|
|
@@ -15401,7 +15706,7 @@ var require_port_for_service_default = createRule({
|
|
|
15401
15706
|
if (node.abstract === true) return;
|
|
15402
15707
|
if (node.decorators.length > 0) return;
|
|
15403
15708
|
const ctor = node.body.body.find(
|
|
15404
|
-
(member) => member.type ===
|
|
15709
|
+
(member) => member.type === AST_NODE_TYPES66.MethodDefinition && member.kind === "constructor" && member.value.body !== null && member.value.body !== void 0
|
|
15405
15710
|
);
|
|
15406
15711
|
if (ctor === void 0) return;
|
|
15407
15712
|
const constructorFacts = readConstructor(
|
|
@@ -15435,8 +15740,120 @@ var require_port_for_service_default = createRule({
|
|
|
15435
15740
|
}
|
|
15436
15741
|
});
|
|
15437
15742
|
|
|
15743
|
+
// src/rules/require-sql-access-class.ts
|
|
15744
|
+
import { AST_NODE_TYPES as AST_NODE_TYPES67 } from "@typescript-eslint/utils";
|
|
15745
|
+
var SQL_METHODS = /* @__PURE__ */ new Set([
|
|
15746
|
+
"all",
|
|
15747
|
+
"batch",
|
|
15748
|
+
"delete",
|
|
15749
|
+
"dump",
|
|
15750
|
+
"exec",
|
|
15751
|
+
"execute",
|
|
15752
|
+
"get",
|
|
15753
|
+
"insert",
|
|
15754
|
+
"pragma",
|
|
15755
|
+
"prepare",
|
|
15756
|
+
"run",
|
|
15757
|
+
"select",
|
|
15758
|
+
"transaction",
|
|
15759
|
+
"update"
|
|
15760
|
+
]);
|
|
15761
|
+
var DATABASE_NAMES = /^(?:db|database|connection|pool|query|transaction|tx)$/iu;
|
|
15762
|
+
var REQUIRE_SQL_ACCESS_CLASS_DOCUMENTATION = {
|
|
15763
|
+
summary: "Keep SQL reads and writes inside a class that receives its database dependency.",
|
|
15764
|
+
rationale: "Free-function database access hides connection ownership and makes transaction, retry, observability, and test boundaries inconsistent.",
|
|
15765
|
+
remediation: "Move the query into a repository or store class and inject the pool, connection, transaction, or typed database binding through its constructor.",
|
|
15766
|
+
category: "architecture",
|
|
15767
|
+
limitations: [
|
|
15768
|
+
"The rule recognizes conventional database receiver names and Cloudflare DB bindings; unusually named or heavily aliased clients require architectural review.",
|
|
15769
|
+
"Query construction without execution is not reported."
|
|
15770
|
+
],
|
|
15771
|
+
examples: [
|
|
15772
|
+
{
|
|
15773
|
+
id: "injected-repository",
|
|
15774
|
+
title: "Own queries in an injected repository",
|
|
15775
|
+
outcome: "no-match",
|
|
15776
|
+
files: [
|
|
15777
|
+
{
|
|
15778
|
+
path: "src/user-repository.ts",
|
|
15779
|
+
source: "export class UserRepository { constructor(private readonly db: Database.Database) {} find(id: string) { return this.db.prepare('SELECT id FROM user WHERE id = ?').get(id); } }"
|
|
15780
|
+
}
|
|
15781
|
+
],
|
|
15782
|
+
focusPath: "src/user-repository.ts",
|
|
15783
|
+
expectedCount: 0,
|
|
15784
|
+
public: true
|
|
15785
|
+
},
|
|
15786
|
+
{
|
|
15787
|
+
id: "free-query",
|
|
15788
|
+
title: "Do not execute SQL in a free function",
|
|
15789
|
+
outcome: "match",
|
|
15790
|
+
files: [
|
|
15791
|
+
{
|
|
15792
|
+
path: "src/users.ts",
|
|
15793
|
+
source: "export function find(database: Database.Database, id: string) { return database.prepare('SELECT id FROM user WHERE id = ?').get(id); }"
|
|
15794
|
+
}
|
|
15795
|
+
],
|
|
15796
|
+
focusPath: "src/users.ts",
|
|
15797
|
+
expectedCount: 1,
|
|
15798
|
+
public: true
|
|
15799
|
+
}
|
|
15800
|
+
]
|
|
15801
|
+
};
|
|
15802
|
+
function memberName4(node) {
|
|
15803
|
+
if (!node.computed && node.property.type === AST_NODE_TYPES67.Identifier)
|
|
15804
|
+
return node.property.name;
|
|
15805
|
+
if (node.computed && node.property.type === AST_NODE_TYPES67.Literal && typeof node.property.value === "string")
|
|
15806
|
+
return node.property.value;
|
|
15807
|
+
return null;
|
|
15808
|
+
}
|
|
15809
|
+
function databaseReceiver(node) {
|
|
15810
|
+
if (node.type === AST_NODE_TYPES67.Identifier)
|
|
15811
|
+
return DATABASE_NAMES.test(node.name);
|
|
15812
|
+
if (node.type !== AST_NODE_TYPES67.MemberExpression) return false;
|
|
15813
|
+
const name = memberName4(node);
|
|
15814
|
+
return name === "DB" || name !== null && DATABASE_NAMES.test(name);
|
|
15815
|
+
}
|
|
15816
|
+
function belongsToClass(node) {
|
|
15817
|
+
let current = node.parent;
|
|
15818
|
+
while (current != null) {
|
|
15819
|
+
if (current.type === AST_NODE_TYPES67.ClassDeclaration || current.type === AST_NODE_TYPES67.ClassExpression)
|
|
15820
|
+
return true;
|
|
15821
|
+
current = current.parent;
|
|
15822
|
+
}
|
|
15823
|
+
return false;
|
|
15824
|
+
}
|
|
15825
|
+
var require_sql_access_class_default = createRule({
|
|
15826
|
+
name: "require-sql-access-class",
|
|
15827
|
+
documentation: REQUIRE_SQL_ACCESS_CLASS_DOCUMENTATION,
|
|
15828
|
+
meta: {
|
|
15829
|
+
type: "suggestion",
|
|
15830
|
+
docs: {
|
|
15831
|
+
description: "Keep SQL reads and writes inside a class that receives its database dependency."
|
|
15832
|
+
},
|
|
15833
|
+
schema: [],
|
|
15834
|
+
messages: {
|
|
15835
|
+
moveSqlIntoClass: "Move this database operation into a repository or store class with an injected connection or pool."
|
|
15836
|
+
}
|
|
15837
|
+
},
|
|
15838
|
+
defaultOptions: [],
|
|
15839
|
+
create(context) {
|
|
15840
|
+
if (isTestFile(context.filename) || isGeneratedFile(context.filename, context.sourceCode.text))
|
|
15841
|
+
return {};
|
|
15842
|
+
return {
|
|
15843
|
+
CallExpression(node) {
|
|
15844
|
+
if (belongsToClass(node) || node.callee.type !== AST_NODE_TYPES67.MemberExpression)
|
|
15845
|
+
return;
|
|
15846
|
+
const method = memberName4(node.callee);
|
|
15847
|
+
if (method === null || !SQL_METHODS.has(method) || !databaseReceiver(node.callee.object))
|
|
15848
|
+
return;
|
|
15849
|
+
context.report({ node, messageId: "moveSqlIntoClass" });
|
|
15850
|
+
}
|
|
15851
|
+
};
|
|
15852
|
+
}
|
|
15853
|
+
});
|
|
15854
|
+
|
|
15438
15855
|
// src/rules/require-static-next-matcher.ts
|
|
15439
|
-
import { AST_NODE_TYPES as
|
|
15856
|
+
import { AST_NODE_TYPES as AST_NODE_TYPES68 } from "@typescript-eslint/utils";
|
|
15440
15857
|
var REQUIRE_STATIC_NEXT_MATCHER_DOCUMENTATION = {
|
|
15441
15858
|
summary: "Require Next.js middleware and proxy matcher configuration to contain only build-time literals.",
|
|
15442
15859
|
rationale: "Next.js must statically analyze matcher values at build time; computed values are ignored.",
|
|
@@ -15449,34 +15866,34 @@ var REQUIRE_STATIC_NEXT_MATCHER_DOCUMENTATION = {
|
|
|
15449
15866
|
};
|
|
15450
15867
|
var NEXT_ENTRY_FILE = /(?:^|[/\\])(?:middleware|proxy)\.[cm]?[jt]sx?$/u;
|
|
15451
15868
|
function unwrapExpression3(node) {
|
|
15452
|
-
if (node.type ===
|
|
15869
|
+
if (node.type === AST_NODE_TYPES68.TSAsExpression || node.type === AST_NODE_TYPES68.TSSatisfiesExpression || node.type === AST_NODE_TYPES68.TSNonNullExpression || node.type === AST_NODE_TYPES68.TSTypeAssertion) {
|
|
15453
15870
|
return unwrapExpression3(node.expression);
|
|
15454
15871
|
}
|
|
15455
15872
|
return node;
|
|
15456
15873
|
}
|
|
15457
15874
|
function isStaticValue(node) {
|
|
15458
15875
|
const value = unwrapExpression3(node);
|
|
15459
|
-
if (value.type ===
|
|
15876
|
+
if (value.type === AST_NODE_TYPES68.Literal) {
|
|
15460
15877
|
return true;
|
|
15461
15878
|
}
|
|
15462
|
-
if (value.type ===
|
|
15879
|
+
if (value.type === AST_NODE_TYPES68.TemplateLiteral) {
|
|
15463
15880
|
return value.expressions.length === 0;
|
|
15464
15881
|
}
|
|
15465
|
-
if (value.type ===
|
|
15882
|
+
if (value.type === AST_NODE_TYPES68.ArrayExpression) {
|
|
15466
15883
|
return value.elements.every(
|
|
15467
|
-
(element) => element !== null && element.type !==
|
|
15884
|
+
(element) => element !== null && element.type !== AST_NODE_TYPES68.SpreadElement && isStaticValue(element)
|
|
15468
15885
|
);
|
|
15469
15886
|
}
|
|
15470
|
-
if (value.type ===
|
|
15887
|
+
if (value.type === AST_NODE_TYPES68.ObjectExpression) {
|
|
15471
15888
|
return value.properties.every(
|
|
15472
|
-
(property) => property.type ===
|
|
15889
|
+
(property) => property.type === AST_NODE_TYPES68.Property && property.kind === "init" && !property.computed && property.value.type !== AST_NODE_TYPES68.AssignmentPattern && isStaticValue(property.value)
|
|
15473
15890
|
);
|
|
15474
15891
|
}
|
|
15475
15892
|
return false;
|
|
15476
15893
|
}
|
|
15477
15894
|
function propertyName4(property) {
|
|
15478
15895
|
if (property.computed) return null;
|
|
15479
|
-
if (property.key.type ===
|
|
15896
|
+
if (property.key.type === AST_NODE_TYPES68.Identifier) return property.key.name;
|
|
15480
15897
|
return typeof property.key.value === "string" ? property.key.value : null;
|
|
15481
15898
|
}
|
|
15482
15899
|
var require_static_next_matcher_default = createRule({
|
|
@@ -15499,19 +15916,19 @@ var require_static_next_matcher_default = createRule({
|
|
|
15499
15916
|
}
|
|
15500
15917
|
return {
|
|
15501
15918
|
ExportNamedDeclaration(node) {
|
|
15502
|
-
if (node.declaration?.type !==
|
|
15919
|
+
if (node.declaration?.type !== AST_NODE_TYPES68.VariableDeclaration) {
|
|
15503
15920
|
return;
|
|
15504
15921
|
}
|
|
15505
15922
|
for (const declaration of node.declaration.declarations) {
|
|
15506
|
-
if (declaration.id.type !==
|
|
15923
|
+
if (declaration.id.type !== AST_NODE_TYPES68.Identifier || declaration.id.name !== "config" || declaration.init === null) {
|
|
15507
15924
|
continue;
|
|
15508
15925
|
}
|
|
15509
15926
|
const config = unwrapExpression3(declaration.init);
|
|
15510
|
-
if (config.type !==
|
|
15927
|
+
if (config.type !== AST_NODE_TYPES68.ObjectExpression) {
|
|
15511
15928
|
continue;
|
|
15512
15929
|
}
|
|
15513
15930
|
for (const property of config.properties) {
|
|
15514
|
-
if (property.type !==
|
|
15931
|
+
if (property.type !== AST_NODE_TYPES68.Property || propertyName4(property) !== "matcher" || property.value.type === AST_NODE_TYPES68.AssignmentPattern) {
|
|
15515
15932
|
continue;
|
|
15516
15933
|
}
|
|
15517
15934
|
if (!isStaticValue(property.value)) {
|
|
@@ -15662,7 +16079,7 @@ var require_use_server_in_actions_file_default = createRule({
|
|
|
15662
16079
|
|
|
15663
16080
|
// src/rules/require-zod-form-validation.ts
|
|
15664
16081
|
import {
|
|
15665
|
-
AST_NODE_TYPES as
|
|
16082
|
+
AST_NODE_TYPES as AST_NODE_TYPES69,
|
|
15666
16083
|
ASTUtils as ASTUtils21
|
|
15667
16084
|
} from "@typescript-eslint/utils";
|
|
15668
16085
|
var REQUIRE_ZOD_FORM_VALIDATION_DOCUMENTATION = {
|
|
@@ -15689,14 +16106,14 @@ var FORM_VALUE_METHODS = /* @__PURE__ */ new Set(["get", "getAll"]);
|
|
|
15689
16106
|
var zodReceiverRoot = (node) => {
|
|
15690
16107
|
let current = node;
|
|
15691
16108
|
while (true) {
|
|
15692
|
-
if (current.type ===
|
|
16109
|
+
if (current.type === AST_NODE_TYPES69.Identifier) {
|
|
15693
16110
|
return current;
|
|
15694
16111
|
}
|
|
15695
|
-
if (current.type ===
|
|
16112
|
+
if (current.type === AST_NODE_TYPES69.CallExpression) {
|
|
15696
16113
|
current = current.callee;
|
|
15697
16114
|
continue;
|
|
15698
16115
|
}
|
|
15699
|
-
if (current.type ===
|
|
16116
|
+
if (current.type === AST_NODE_TYPES69.MemberExpression) {
|
|
15700
16117
|
current = current.object;
|
|
15701
16118
|
continue;
|
|
15702
16119
|
}
|
|
@@ -15705,12 +16122,12 @@ var zodReceiverRoot = (node) => {
|
|
|
15705
16122
|
};
|
|
15706
16123
|
var isFormDataMethodCall = (node) => {
|
|
15707
16124
|
let current = node;
|
|
15708
|
-
if (current.type ===
|
|
16125
|
+
if (current.type === AST_NODE_TYPES69.AwaitExpression) {
|
|
15709
16126
|
current = current.argument;
|
|
15710
16127
|
}
|
|
15711
|
-
if (current.type !==
|
|
16128
|
+
if (current.type !== AST_NODE_TYPES69.CallExpression) return false;
|
|
15712
16129
|
const callee = current.callee;
|
|
15713
|
-
return callee.type ===
|
|
16130
|
+
return callee.type === AST_NODE_TYPES69.MemberExpression && !callee.computed && callee.property.type === AST_NODE_TYPES69.Identifier && callee.property.name === "formData";
|
|
15714
16131
|
};
|
|
15715
16132
|
var require_zod_form_validation_default = createRule({
|
|
15716
16133
|
name: "require-zod-form-validation",
|
|
@@ -15741,16 +16158,16 @@ var require_zod_form_validation_default = createRule({
|
|
|
15741
16158
|
return false;
|
|
15742
16159
|
}
|
|
15743
16160
|
const definition = binding.defs[0];
|
|
15744
|
-
if (definition?.type !== "Variable" || definition.node.type !==
|
|
16161
|
+
if (definition?.type !== "Variable" || definition.node.type !== AST_NODE_TYPES69.VariableDeclarator) {
|
|
15745
16162
|
return false;
|
|
15746
16163
|
}
|
|
15747
16164
|
const init = definition.node.init;
|
|
15748
|
-
return init?.type ===
|
|
16165
|
+
return init?.type === AST_NODE_TYPES69.ObjectExpression || init?.type === AST_NODE_TYPES69.ArrayExpression || init?.type === AST_NODE_TYPES69.Literal || init?.type === AST_NODE_TYPES69.ArrowFunctionExpression || init?.type === AST_NODE_TYPES69.FunctionExpression;
|
|
15749
16166
|
};
|
|
15750
16167
|
const isZodParseCall = (node) => {
|
|
15751
|
-
if (node.type !==
|
|
16168
|
+
if (node.type !== AST_NODE_TYPES69.CallExpression) return false;
|
|
15752
16169
|
const callee = node.callee;
|
|
15753
|
-
if (callee.type !==
|
|
16170
|
+
if (callee.type !== AST_NODE_TYPES69.MemberExpression || callee.computed || callee.property.type !== AST_NODE_TYPES69.Identifier || !ZOD_PARSE_METHODS.has(callee.property.name)) {
|
|
15754
16171
|
return false;
|
|
15755
16172
|
}
|
|
15756
16173
|
const root = zodReceiverRoot(callee.object);
|
|
@@ -15759,14 +16176,14 @@ var require_zod_form_validation_default = createRule({
|
|
|
15759
16176
|
return binding !== null && zodBindings.has(binding) || (root.name === "z" || ZOD_SCHEMA_NAME_RE.test(root.name)) && !isProvablyNonZodLocal(root);
|
|
15760
16177
|
};
|
|
15761
16178
|
const isFormSourceIdentifier = (node) => {
|
|
15762
|
-
if (node.type !==
|
|
16179
|
+
if (node.type !== AST_NODE_TYPES69.Identifier) return false;
|
|
15763
16180
|
const conventionalName = /formdata/i.test(node.name);
|
|
15764
16181
|
let scope = context.sourceCode.getScope(node);
|
|
15765
16182
|
while (scope !== null) {
|
|
15766
16183
|
const variable = scope.set.get(node.name);
|
|
15767
16184
|
if (variable !== void 0 && variable.defs.length === 1) {
|
|
15768
16185
|
const def = variable.defs[0];
|
|
15769
|
-
if (def !== void 0 && def.type === "Variable" && def.node.type ===
|
|
16186
|
+
if (def !== void 0 && def.type === "Variable" && def.node.type === AST_NODE_TYPES69.VariableDeclarator && def.node.init !== null) {
|
|
15770
16187
|
return isFormDataMethodCall(def.node.init);
|
|
15771
16188
|
}
|
|
15772
16189
|
return def?.type === "Parameter" && conventionalName;
|
|
@@ -15777,8 +16194,8 @@ var require_zod_form_validation_default = createRule({
|
|
|
15777
16194
|
};
|
|
15778
16195
|
const isFormDataGetCall = (node) => {
|
|
15779
16196
|
const callee = node.callee;
|
|
15780
|
-
if (callee.type !==
|
|
15781
|
-
if (callee.property.type !==
|
|
16197
|
+
if (callee.type !== AST_NODE_TYPES69.MemberExpression) return false;
|
|
16198
|
+
if (callee.property.type !== AST_NODE_TYPES69.Identifier || !FORM_VALUE_METHODS.has(callee.property.name)) {
|
|
15782
16199
|
return false;
|
|
15783
16200
|
}
|
|
15784
16201
|
return isFormSourceIdentifier(callee.object);
|
|
@@ -15794,16 +16211,16 @@ var require_zod_form_validation_default = createRule({
|
|
|
15794
16211
|
const hasZodParseAncestor = (node) => zodParseAncestor(node) !== null;
|
|
15795
16212
|
const isInstanceofNarrowing = (node) => {
|
|
15796
16213
|
const parent = node.parent;
|
|
15797
|
-
return parent !== null && parent !== void 0 && parent.type ===
|
|
16214
|
+
return parent !== null && parent !== void 0 && parent.type === AST_NODE_TYPES69.BinaryExpression && parent.operator === "instanceof" && parent.left === node && parent.right.type === AST_NODE_TYPES69.Identifier && (parent.right.name === "File" || parent.right.name === "Blob");
|
|
15798
16215
|
};
|
|
15799
16216
|
const boundDeclarator = (node) => {
|
|
15800
16217
|
let current = node;
|
|
15801
16218
|
let parent = current.parent;
|
|
15802
|
-
while ((parent.type ===
|
|
16219
|
+
while ((parent.type === AST_NODE_TYPES69.TSAsExpression || parent.type === AST_NODE_TYPES69.TSSatisfiesExpression || parent.type === AST_NODE_TYPES69.TSNonNullExpression || parent.type === AST_NODE_TYPES69.ChainExpression) && parent.expression === current) {
|
|
15803
16220
|
current = parent;
|
|
15804
16221
|
parent = current.parent;
|
|
15805
16222
|
}
|
|
15806
|
-
if (parent.type ===
|
|
16223
|
+
if (parent.type === AST_NODE_TYPES69.VariableDeclarator && parent.init === current && parent.id.type === AST_NODE_TYPES69.Identifier) {
|
|
15807
16224
|
return parent;
|
|
15808
16225
|
}
|
|
15809
16226
|
return null;
|
|
@@ -15812,7 +16229,7 @@ var require_zod_form_validation_default = createRule({
|
|
|
15812
16229
|
let current = node;
|
|
15813
16230
|
while (current.parent !== void 0) {
|
|
15814
16231
|
const parent = current.parent;
|
|
15815
|
-
if (parent.type ===
|
|
16232
|
+
if (parent.type === AST_NODE_TYPES69.BlockStatement || parent.type === AST_NODE_TYPES69.Program) {
|
|
15816
16233
|
return current;
|
|
15817
16234
|
}
|
|
15818
16235
|
current = parent;
|
|
@@ -15821,12 +16238,12 @@ var require_zod_form_validation_default = createRule({
|
|
|
15821
16238
|
};
|
|
15822
16239
|
const zodParseMethod = (call) => {
|
|
15823
16240
|
const callee = call.callee;
|
|
15824
|
-
return callee.type ===
|
|
16241
|
+
return callee.type === AST_NODE_TYPES69.MemberExpression && !callee.computed && callee.property.type === AST_NODE_TYPES69.Identifier ? callee.property.name : null;
|
|
15825
16242
|
};
|
|
15826
16243
|
const hasConditionalAncestorBeforeStatement = (node, statement) => {
|
|
15827
16244
|
let current = node.parent;
|
|
15828
16245
|
while (current !== void 0 && current !== statement) {
|
|
15829
|
-
if (current.type ===
|
|
16246
|
+
if (current.type === AST_NODE_TYPES69.LogicalExpression || current.type === AST_NODE_TYPES69.ConditionalExpression) {
|
|
15830
16247
|
return true;
|
|
15831
16248
|
}
|
|
15832
16249
|
current = current.parent;
|
|
@@ -15836,7 +16253,7 @@ var require_zod_form_validation_default = createRule({
|
|
|
15836
16253
|
const isAwaitedBeforeStatement = (node, statement) => {
|
|
15837
16254
|
let current = node.parent;
|
|
15838
16255
|
while (current !== void 0 && current !== statement) {
|
|
15839
|
-
if (current.type ===
|
|
16256
|
+
if (current.type === AST_NODE_TYPES69.AwaitExpression) return true;
|
|
15840
16257
|
current = current.parent;
|
|
15841
16258
|
}
|
|
15842
16259
|
return false;
|
|
@@ -15849,7 +16266,7 @@ var require_zod_form_validation_default = createRule({
|
|
|
15849
16266
|
if (declarationStatement === null || validationStatement === null || declarationStatement.parent !== validationStatement.parent || validationStatement.range[0] <= declarationStatement.range[1] || hasConditionalAncestorBeforeStatement(parse2, validationStatement)) {
|
|
15850
16267
|
return null;
|
|
15851
16268
|
}
|
|
15852
|
-
if (validationStatement.type !==
|
|
16269
|
+
if (validationStatement.type !== AST_NODE_TYPES69.VariableDeclaration && validationStatement.type !== AST_NODE_TYPES69.ExpressionStatement) {
|
|
15853
16270
|
return null;
|
|
15854
16271
|
}
|
|
15855
16272
|
const method = zodParseMethod(parse2);
|
|
@@ -15861,16 +16278,16 @@ var require_zod_form_validation_default = createRule({
|
|
|
15861
16278
|
};
|
|
15862
16279
|
const isSafePrevalidationInspection = (identifier) => {
|
|
15863
16280
|
const parent = identifier.parent;
|
|
15864
|
-
if (parent.type ===
|
|
16281
|
+
if (parent.type === AST_NODE_TYPES69.UnaryExpression && parent.operator === "typeof") {
|
|
15865
16282
|
return true;
|
|
15866
16283
|
}
|
|
15867
|
-
if (parent.type !==
|
|
16284
|
+
if (parent.type !== AST_NODE_TYPES69.BinaryExpression || parent.left !== identifier) {
|
|
15868
16285
|
return false;
|
|
15869
16286
|
}
|
|
15870
16287
|
if (parent.operator === "instanceof") {
|
|
15871
|
-
return parent.right.type ===
|
|
16288
|
+
return parent.right.type === AST_NODE_TYPES69.Identifier && (parent.right.name === "File" || parent.right.name === "Blob");
|
|
15872
16289
|
}
|
|
15873
|
-
return ["===", "!==", "==", "!="].includes(parent.operator) && (parent.right.type ===
|
|
16290
|
+
return ["===", "!==", "==", "!="].includes(parent.operator) && (parent.right.type === AST_NODE_TYPES69.Literal && parent.right.value === null || parent.right.type === AST_NODE_TYPES69.Identifier && parent.right.name === "undefined");
|
|
15874
16291
|
};
|
|
15875
16292
|
const isDescendantOf = (node, ancestor) => {
|
|
15876
16293
|
let current = node;
|
|
@@ -15881,23 +16298,23 @@ var require_zod_form_validation_default = createRule({
|
|
|
15881
16298
|
return false;
|
|
15882
16299
|
};
|
|
15883
16300
|
const blockTerminates = (node) => {
|
|
15884
|
-
if (node.type ===
|
|
16301
|
+
if (node.type === AST_NODE_TYPES69.ReturnStatement || node.type === AST_NODE_TYPES69.ThrowStatement) {
|
|
15885
16302
|
return true;
|
|
15886
16303
|
}
|
|
15887
|
-
if (node.type !==
|
|
16304
|
+
if (node.type !== AST_NODE_TYPES69.BlockStatement || node.body.length === 0) return false;
|
|
15888
16305
|
const last = node.body.at(-1);
|
|
15889
16306
|
return last !== void 0 && blockTerminates(last);
|
|
15890
16307
|
};
|
|
15891
16308
|
const narrowingIf = (identifier) => {
|
|
15892
16309
|
const comparison = identifier.parent;
|
|
15893
|
-
if (comparison?.type !==
|
|
16310
|
+
if (comparison?.type !== AST_NODE_TYPES69.BinaryExpression || comparison.operator !== "instanceof" || comparison.left !== identifier || comparison.right.type !== AST_NODE_TYPES69.Identifier || comparison.right.name !== "File" && comparison.right.name !== "Blob") {
|
|
15894
16311
|
return null;
|
|
15895
16312
|
}
|
|
15896
16313
|
const maybeNegation = comparison.parent;
|
|
15897
|
-
const negated = maybeNegation?.type ===
|
|
16314
|
+
const negated = maybeNegation?.type === AST_NODE_TYPES69.UnaryExpression && maybeNegation.operator === "!";
|
|
15898
16315
|
const test = negated ? maybeNegation : comparison;
|
|
15899
16316
|
const branch = test.parent;
|
|
15900
|
-
return branch?.type ===
|
|
16317
|
+
return branch?.type === AST_NODE_TYPES69.IfStatement && branch.test === test ? { branch, positive: !negated } : null;
|
|
15901
16318
|
};
|
|
15902
16319
|
const useDominatedByNarrowing = (use, narrowings) => narrowings.some(({ branch, positive }) => {
|
|
15903
16320
|
if (positive) return isDescendantOf(use, branch.consequent);
|
|
@@ -15917,7 +16334,7 @@ var require_zod_form_validation_default = createRule({
|
|
|
15917
16334
|
const variable = context.sourceCode.getDeclaredVariables(declarator)[0];
|
|
15918
16335
|
if (variable === void 0) return false;
|
|
15919
16336
|
const references = variable.references.filter((reference) => !reference.isWriteOnly()).map((reference) => reference.identifier).filter(
|
|
15920
|
-
(identifier) => identifier.type ===
|
|
16337
|
+
(identifier) => identifier.type === AST_NODE_TYPES69.Identifier
|
|
15921
16338
|
);
|
|
15922
16339
|
if (references.length === 0) return false;
|
|
15923
16340
|
const narrowings = references.map(narrowingIf).filter(
|
|
@@ -15943,7 +16360,7 @@ var require_zod_form_validation_default = createRule({
|
|
|
15943
16360
|
ImportDeclaration(node) {
|
|
15944
16361
|
if (!isZodModule(node.source.value)) return;
|
|
15945
16362
|
for (const specifier of node.specifiers) {
|
|
15946
|
-
if (specifier.type ===
|
|
16363
|
+
if (specifier.type === AST_NODE_TYPES69.ImportNamespaceSpecifier || specifier.type === AST_NODE_TYPES69.ImportDefaultSpecifier || specifier.type === AST_NODE_TYPES69.ImportSpecifier && (specifier.imported.type === AST_NODE_TYPES69.Identifier ? specifier.imported.name === "z" : specifier.imported.value === "z")) {
|
|
15947
16364
|
const binding = resolvedBinding(specifier.local);
|
|
15948
16365
|
if (binding !== null) zodBindings.add(binding);
|
|
15949
16366
|
}
|
|
@@ -16028,7 +16445,7 @@ var store_insert_requires_on_conflict_default = createRule({
|
|
|
16028
16445
|
});
|
|
16029
16446
|
|
|
16030
16447
|
// src/rules/stepdown.ts
|
|
16031
|
-
import { AST_NODE_TYPES as
|
|
16448
|
+
import { AST_NODE_TYPES as AST_NODE_TYPES70, ASTUtils as ASTUtils22 } from "@typescript-eslint/utils";
|
|
16032
16449
|
var STEPDOWN_DOCUMENTATION = {
|
|
16033
16450
|
summary: "Place a private helper below its sole direct same-scope caller.",
|
|
16034
16451
|
rationale: "Caller-first ordering lets a reader follow the main flow before descending into implementation details.",
|
|
@@ -16048,7 +16465,7 @@ var STEPDOWN_DOCUMENTATION = {
|
|
|
16048
16465
|
]
|
|
16049
16466
|
};
|
|
16050
16467
|
function isFunction(node) {
|
|
16051
|
-
return node.type ===
|
|
16468
|
+
return node.type === AST_NODE_TYPES70.ArrowFunctionExpression || node.type === AST_NODE_TYPES70.FunctionDeclaration || node.type === AST_NODE_TYPES70.FunctionExpression;
|
|
16052
16469
|
}
|
|
16053
16470
|
function reportMisordered(context, candidates, scopeDefinitions, calls, pinned, canMove = () => true, makeFix) {
|
|
16054
16471
|
const byName = new Map(scopeDefinitions.map((definition) => [definition.name, definition]));
|
|
@@ -16145,8 +16562,8 @@ function moduleScope(context, program) {
|
|
|
16145
16562
|
for (const node of declarations) counts.set(node.name, (counts.get(node.name) ?? 0) + 1);
|
|
16146
16563
|
const overloadNames = new Set(
|
|
16147
16564
|
program.body.flatMap((statement) => {
|
|
16148
|
-
const node = statement.type ===
|
|
16149
|
-
return node?.type ===
|
|
16565
|
+
const node = statement.type === AST_NODE_TYPES70.ExportNamedDeclaration ? statement.declaration : statement;
|
|
16566
|
+
return node?.type === AST_NODE_TYPES70.TSDeclareFunction && node.id !== null ? [node.id.name] : [];
|
|
16150
16567
|
})
|
|
16151
16568
|
);
|
|
16152
16569
|
const exported = exportedNames(program);
|
|
@@ -16170,7 +16587,7 @@ function moduleScope(context, program) {
|
|
|
16170
16587
|
const nearestFunction2 = [...ancestors].reverse().find(isFunction);
|
|
16171
16588
|
const parent = identifier.parent;
|
|
16172
16589
|
const callerDefinition = nearestFunction2 === void 0 ? void 0 : byFunction.get(nearestFunction2);
|
|
16173
|
-
if (callerDefinition === void 0 || parent.type !==
|
|
16590
|
+
if (callerDefinition === void 0 || parent.type !== AST_NODE_TYPES70.CallExpression || parent.callee !== identifier) {
|
|
16174
16591
|
pinned.add(definition.name);
|
|
16175
16592
|
continue;
|
|
16176
16593
|
}
|
|
@@ -16185,38 +16602,38 @@ function moduleScope(context, program) {
|
|
|
16185
16602
|
function exportedNames(program) {
|
|
16186
16603
|
const names = /* @__PURE__ */ new Set();
|
|
16187
16604
|
for (const statement of program.body) {
|
|
16188
|
-
if (statement.type !==
|
|
16189
|
-
if (statement.declaration?.type ===
|
|
16605
|
+
if (statement.type !== AST_NODE_TYPES70.ExportNamedDeclaration || statement.exportKind === "type" || statement.source !== null) continue;
|
|
16606
|
+
if (statement.declaration?.type === AST_NODE_TYPES70.FunctionDeclaration && statement.declaration.id !== null) {
|
|
16190
16607
|
names.add(statement.declaration.id.name);
|
|
16191
16608
|
}
|
|
16192
|
-
if (statement.declaration?.type ===
|
|
16609
|
+
if (statement.declaration?.type === AST_NODE_TYPES70.VariableDeclaration) {
|
|
16193
16610
|
for (const declarator of statement.declaration.declarations) {
|
|
16194
|
-
if (declarator.id.type ===
|
|
16611
|
+
if (declarator.id.type === AST_NODE_TYPES70.Identifier) names.add(declarator.id.name);
|
|
16195
16612
|
}
|
|
16196
16613
|
}
|
|
16197
16614
|
for (const specifier of statement.specifiers) {
|
|
16198
|
-
if (specifier.exportKind !== "type" && specifier.local.type ===
|
|
16615
|
+
if (specifier.exportKind !== "type" && specifier.local.type === AST_NODE_TYPES70.Identifier) {
|
|
16199
16616
|
names.add(specifier.local.name);
|
|
16200
16617
|
}
|
|
16201
16618
|
}
|
|
16202
16619
|
}
|
|
16203
16620
|
for (const statement of program.body) {
|
|
16204
|
-
if (statement.type ===
|
|
16205
|
-
if (statement.type ===
|
|
16621
|
+
if (statement.type === AST_NODE_TYPES70.ExportDefaultDeclaration && statement.declaration.type === AST_NODE_TYPES70.Identifier) names.add(statement.declaration.name);
|
|
16622
|
+
if (statement.type === AST_NODE_TYPES70.ExportDefaultDeclaration && statement.declaration.type === AST_NODE_TYPES70.FunctionDeclaration && statement.declaration.id !== null) names.add(statement.declaration.id.name);
|
|
16206
16623
|
}
|
|
16207
16624
|
return names;
|
|
16208
16625
|
}
|
|
16209
16626
|
function moduleDefinitions(program) {
|
|
16210
16627
|
const definitions = [];
|
|
16211
16628
|
for (const statement of program.body) {
|
|
16212
|
-
const node = statement.type ===
|
|
16213
|
-
if (node?.type ===
|
|
16629
|
+
const node = statement.type === AST_NODE_TYPES70.ExportNamedDeclaration || statement.type === AST_NODE_TYPES70.ExportDefaultDeclaration ? statement.declaration : statement;
|
|
16630
|
+
if (node?.type === AST_NODE_TYPES70.FunctionDeclaration && node.id !== null && node.body !== null) {
|
|
16214
16631
|
definitions.push({ name: node.id.name, node, functionNode: node, bindingNode: node });
|
|
16215
16632
|
continue;
|
|
16216
16633
|
}
|
|
16217
|
-
if (node?.type !==
|
|
16634
|
+
if (node?.type !== AST_NODE_TYPES70.VariableDeclaration || node.kind !== "const") continue;
|
|
16218
16635
|
for (const declarator of node.declarations) {
|
|
16219
|
-
if (declarator.id.type ===
|
|
16636
|
+
if (declarator.id.type === AST_NODE_TYPES70.Identifier && declarator.init !== null && isFunction(declarator.init)) {
|
|
16220
16637
|
definitions.push({
|
|
16221
16638
|
name: declarator.id.name,
|
|
16222
16639
|
node: declarator,
|
|
@@ -16229,21 +16646,21 @@ function moduleDefinitions(program) {
|
|
|
16229
16646
|
return definitions;
|
|
16230
16647
|
}
|
|
16231
16648
|
function methodName(node) {
|
|
16232
|
-
if (node.key.type ===
|
|
16233
|
-
return !node.computed && node.key.type ===
|
|
16649
|
+
if (node.key.type === AST_NODE_TYPES70.PrivateIdentifier) return `#${node.key.name}`;
|
|
16650
|
+
return !node.computed && node.key.type === AST_NODE_TYPES70.Identifier ? node.key.name : null;
|
|
16234
16651
|
}
|
|
16235
16652
|
function referencedMethod(context, node, classVariables) {
|
|
16236
|
-
const objectVariable = node.object.type ===
|
|
16653
|
+
const objectVariable = node.object.type === AST_NODE_TYPES70.Identifier ? ASTUtils22.findVariable(context.sourceCode.getScope(node.object), node.object.name) : null;
|
|
16237
16654
|
const isClassReference = objectVariable !== null && classVariables.has(objectVariable);
|
|
16238
|
-
if (node.object.type !==
|
|
16239
|
-
if (node.property.type ===
|
|
16240
|
-
if (!node.computed && node.property.type ===
|
|
16241
|
-
return node.computed && node.property.type ===
|
|
16655
|
+
if (node.object.type !== AST_NODE_TYPES70.ThisExpression && !isClassReference) return null;
|
|
16656
|
+
if (node.property.type === AST_NODE_TYPES70.PrivateIdentifier) return `#${node.property.name}`;
|
|
16657
|
+
if (!node.computed && node.property.type === AST_NODE_TYPES70.Identifier) return node.property.name;
|
|
16658
|
+
return node.computed && node.property.type === AST_NODE_TYPES70.Literal && typeof node.property.value === "string" ? node.property.value : null;
|
|
16242
16659
|
}
|
|
16243
16660
|
function referencedPropertyName(node) {
|
|
16244
|
-
if (node.property.type ===
|
|
16245
|
-
if (!node.computed && node.property.type ===
|
|
16246
|
-
return node.computed && node.property.type ===
|
|
16661
|
+
if (node.property.type === AST_NODE_TYPES70.PrivateIdentifier) return `#${node.property.name}`;
|
|
16662
|
+
if (!node.computed && node.property.type === AST_NODE_TYPES70.Identifier) return node.property.name;
|
|
16663
|
+
return node.computed && node.property.type === AST_NODE_TYPES70.Literal && typeof node.property.value === "string" ? node.property.value : null;
|
|
16247
16664
|
}
|
|
16248
16665
|
function walk2(node, visitorKeys, visit, nestedFunction = false) {
|
|
16249
16666
|
visit(node, nestedFunction);
|
|
@@ -16259,7 +16676,7 @@ function walk2(node, visitorKeys, visit, nestedFunction = false) {
|
|
|
16259
16676
|
}
|
|
16260
16677
|
function classScope(context, node, computedReferenceNames) {
|
|
16261
16678
|
const methods = node.body.body.filter(
|
|
16262
|
-
(member) => member.type ===
|
|
16679
|
+
(member) => member.type === AST_NODE_TYPES70.MethodDefinition
|
|
16263
16680
|
);
|
|
16264
16681
|
const counts = /* @__PURE__ */ new Map();
|
|
16265
16682
|
for (const method of methods) {
|
|
@@ -16267,8 +16684,8 @@ function classScope(context, node, computedReferenceNames) {
|
|
|
16267
16684
|
if (name !== null) counts.set(name, (counts.get(name) ?? 0) + 1);
|
|
16268
16685
|
}
|
|
16269
16686
|
for (const member of node.body.body) {
|
|
16270
|
-
if (member.type !==
|
|
16271
|
-
const name = !member.computed && member.key.type ===
|
|
16687
|
+
if (member.type !== AST_NODE_TYPES70.TSAbstractMethodDefinition) continue;
|
|
16688
|
+
const name = !member.computed && member.key.type === AST_NODE_TYPES70.Identifier ? member.key.name : null;
|
|
16272
16689
|
if (name !== null) counts.set(name, (counts.get(name) ?? 0) + 1);
|
|
16273
16690
|
}
|
|
16274
16691
|
const scopeDefinitions = methods.flatMap((method) => {
|
|
@@ -16277,7 +16694,7 @@ function classScope(context, node, computedReferenceNames) {
|
|
|
16277
16694
|
});
|
|
16278
16695
|
const definitions = methods.flatMap((method) => {
|
|
16279
16696
|
const name = methodName(method);
|
|
16280
|
-
const isPrivate = method.accessibility === "private" || method.key.type ===
|
|
16697
|
+
const isPrivate = method.accessibility === "private" || method.key.type === AST_NODE_TYPES70.PrivateIdentifier;
|
|
16281
16698
|
return name !== null && isPrivate && counts.get(name) === 1 && method.decorators.length === 0 ? [{ name, node: method }] : [];
|
|
16282
16699
|
});
|
|
16283
16700
|
if (definitions.length === 0) return;
|
|
@@ -16289,7 +16706,7 @@ function classScope(context, node, computedReferenceNames) {
|
|
|
16289
16706
|
const internal = ASTUtils22.findVariable(context.sourceCode.getScope(node), node.id.name);
|
|
16290
16707
|
if (internal !== null) classVariables.add(internal);
|
|
16291
16708
|
}
|
|
16292
|
-
if (node.type ===
|
|
16709
|
+
if (node.type === AST_NODE_TYPES70.ClassExpression && node.parent.type === AST_NODE_TYPES70.VariableDeclarator && node.parent.id.type === AST_NODE_TYPES70.Identifier) {
|
|
16293
16710
|
const outer = ASTUtils22.findVariable(context.sourceCode.getScope(node.parent), node.parent.id.name);
|
|
16294
16711
|
if (outer !== null) classVariables.add(outer);
|
|
16295
16712
|
}
|
|
@@ -16306,26 +16723,26 @@ function classScope(context, node, computedReferenceNames) {
|
|
|
16306
16723
|
}
|
|
16307
16724
|
const thisValue = (value) => {
|
|
16308
16725
|
let current = value;
|
|
16309
|
-
while (current?.type ===
|
|
16310
|
-
return current?.type ===
|
|
16726
|
+
while (current?.type === AST_NODE_TYPES70.TSAsExpression || current?.type === AST_NODE_TYPES70.TSSatisfiesExpression || current?.type === AST_NODE_TYPES70.TSNonNullExpression) current = current.expression;
|
|
16727
|
+
return current?.type === AST_NODE_TYPES70.ThisExpression;
|
|
16311
16728
|
};
|
|
16312
16729
|
const collectAlias = (current, nestedFunction) => {
|
|
16313
|
-
if (nestedFunction || current.type !==
|
|
16314
|
-
if (current.type ===
|
|
16315
|
-
const binding = current.type ===
|
|
16316
|
-
const value = current.type ===
|
|
16730
|
+
if (nestedFunction || current.type !== AST_NODE_TYPES70.VariableDeclarator && current.type !== AST_NODE_TYPES70.AssignmentPattern) return;
|
|
16731
|
+
if (current.type === AST_NODE_TYPES70.VariableDeclarator && (current.parent.type !== AST_NODE_TYPES70.VariableDeclaration || current.parent.kind !== "const")) return;
|
|
16732
|
+
const binding = current.type === AST_NODE_TYPES70.VariableDeclarator ? current.id : current.left;
|
|
16733
|
+
const value = current.type === AST_NODE_TYPES70.VariableDeclarator ? current.init : current.right;
|
|
16317
16734
|
if (!thisValue(value)) return;
|
|
16318
|
-
if (binding.type ===
|
|
16735
|
+
if (binding.type === AST_NODE_TYPES70.ObjectPattern) {
|
|
16319
16736
|
for (const property of binding.properties) {
|
|
16320
|
-
if (property.type ===
|
|
16737
|
+
if (property.type === AST_NODE_TYPES70.RestElement) {
|
|
16321
16738
|
for (const name of privateNames) pinned.add(name);
|
|
16322
|
-
} else if (property.key.type ===
|
|
16739
|
+
} else if (property.key.type === AST_NODE_TYPES70.Identifier && privateNames.has(property.key.name)) {
|
|
16323
16740
|
pinned.add(property.key.name);
|
|
16324
16741
|
}
|
|
16325
16742
|
}
|
|
16326
16743
|
return;
|
|
16327
16744
|
}
|
|
16328
|
-
if (binding.type !==
|
|
16745
|
+
if (binding.type !== AST_NODE_TYPES70.Identifier) return;
|
|
16329
16746
|
const variable = ASTUtils22.findVariable(context.sourceCode.getScope(binding), binding.name);
|
|
16330
16747
|
if (variable !== null) {
|
|
16331
16748
|
methodClassVariables.add(variable);
|
|
@@ -16339,16 +16756,16 @@ function classScope(context, node, computedReferenceNames) {
|
|
|
16339
16756
|
walk2(statement, context.sourceCode.visitorKeys, collectAlias);
|
|
16340
16757
|
}
|
|
16341
16758
|
const visitCall = (current, nestedFunction) => {
|
|
16342
|
-
if (current.type ===
|
|
16759
|
+
if (current.type === AST_NODE_TYPES70.VariableDeclarator && current.id.type === AST_NODE_TYPES70.ObjectPattern && thisValue(current.init)) {
|
|
16343
16760
|
for (const property of current.id.properties) {
|
|
16344
|
-
if (property.type ===
|
|
16761
|
+
if (property.type === AST_NODE_TYPES70.RestElement) {
|
|
16345
16762
|
for (const name of privateNames) pinned.add(name);
|
|
16346
16763
|
continue;
|
|
16347
16764
|
}
|
|
16348
|
-
if (property.type ===
|
|
16765
|
+
if (property.type === AST_NODE_TYPES70.Property && property.key.type === AST_NODE_TYPES70.Identifier && privateNames.has(property.key.name)) pinned.add(property.key.name);
|
|
16349
16766
|
}
|
|
16350
16767
|
}
|
|
16351
|
-
if (current.type !==
|
|
16768
|
+
if (current.type !== AST_NODE_TYPES70.MemberExpression) return;
|
|
16352
16769
|
const target = referencedMethod(context, current, methodClassVariables);
|
|
16353
16770
|
if (target === null) {
|
|
16354
16771
|
const possibleTarget = referencedPropertyName(current);
|
|
@@ -16356,12 +16773,12 @@ function classScope(context, node, computedReferenceNames) {
|
|
|
16356
16773
|
return;
|
|
16357
16774
|
}
|
|
16358
16775
|
if (!privateNames.has(target)) return;
|
|
16359
|
-
const objectVariable = current.object.type ===
|
|
16776
|
+
const objectVariable = current.object.type === AST_NODE_TYPES70.Identifier ? ASTUtils22.findVariable(context.sourceCode.getScope(current.object), current.object.name) : null;
|
|
16360
16777
|
if (objectVariable !== null && methodAliases.has(objectVariable)) {
|
|
16361
16778
|
pinned.add(target);
|
|
16362
16779
|
return;
|
|
16363
16780
|
}
|
|
16364
|
-
if (current.computed || nestedFunction || parameterDecoratorNodes.has(current) || current.parent.type !==
|
|
16781
|
+
if (current.computed || nestedFunction || parameterDecoratorNodes.has(current) || current.parent.type !== AST_NODE_TYPES70.CallExpression || current.parent.callee !== current) {
|
|
16365
16782
|
pinned.add(target);
|
|
16366
16783
|
return;
|
|
16367
16784
|
}
|
|
@@ -16381,9 +16798,9 @@ function classScope(context, node, computedReferenceNames) {
|
|
|
16381
16798
|
}
|
|
16382
16799
|
}
|
|
16383
16800
|
for (const member of node.body.body) {
|
|
16384
|
-
if (member.type ===
|
|
16801
|
+
if (member.type === AST_NODE_TYPES70.MethodDefinition || member.type === AST_NODE_TYPES70.TSAbstractMethodDefinition) continue;
|
|
16385
16802
|
walk2(member, context.sourceCode.visitorKeys, (current) => {
|
|
16386
|
-
if (current.type !==
|
|
16803
|
+
if (current.type !== AST_NODE_TYPES70.MemberExpression) return;
|
|
16387
16804
|
const target = referencedMethod(context, current, classVariables);
|
|
16388
16805
|
const possibleTarget = target ?? referencedPropertyName(current);
|
|
16389
16806
|
if (possibleTarget !== null && privateNames.has(possibleTarget)) pinned.add(possibleTarget);
|
|
@@ -16435,12 +16852,12 @@ function classScope(context, node, computedReferenceNames) {
|
|
|
16435
16852
|
}
|
|
16436
16853
|
function isClassRuntimeBarrier(member) {
|
|
16437
16854
|
switch (member.type) {
|
|
16438
|
-
case
|
|
16855
|
+
case AST_NODE_TYPES70.StaticBlock:
|
|
16439
16856
|
return true;
|
|
16440
|
-
case
|
|
16441
|
-
case
|
|
16857
|
+
case AST_NODE_TYPES70.PropertyDefinition:
|
|
16858
|
+
case AST_NODE_TYPES70.AccessorProperty:
|
|
16442
16859
|
return member.static || member.computed || member.decorators.length > 0 || member.value !== null;
|
|
16443
|
-
case
|
|
16860
|
+
case AST_NODE_TYPES70.MethodDefinition:
|
|
16444
16861
|
return member.computed || member.decorators.length > 0;
|
|
16445
16862
|
default:
|
|
16446
16863
|
return false;
|
|
@@ -16473,7 +16890,7 @@ var stepdown_default = createRule({
|
|
|
16473
16890
|
moduleScope(context, program);
|
|
16474
16891
|
const computedReferenceNames = /* @__PURE__ */ new Set();
|
|
16475
16892
|
walk2(program, context.sourceCode.visitorKeys, (node) => {
|
|
16476
|
-
if (node.type ===
|
|
16893
|
+
if (node.type === AST_NODE_TYPES70.MemberExpression && node.computed && node.property.type === AST_NODE_TYPES70.Literal && typeof node.property.value === "string") computedReferenceNames.add(node.property.value);
|
|
16477
16894
|
});
|
|
16478
16895
|
for (const node of classes) classScope(context, node, computedReferenceNames);
|
|
16479
16896
|
}
|
|
@@ -16482,7 +16899,7 @@ var stepdown_default = createRule({
|
|
|
16482
16899
|
});
|
|
16483
16900
|
|
|
16484
16901
|
// src/rules/source-coupled-test.ts
|
|
16485
|
-
import { AST_NODE_TYPES as
|
|
16902
|
+
import { AST_NODE_TYPES as AST_NODE_TYPES71 } from "@typescript-eslint/utils";
|
|
16486
16903
|
var GENERAL_SOURCE_SUFFIX_RE = /\.(?:bash|sh|ya?ml|jsonc|py|[cm]?[jt]s)$/iu;
|
|
16487
16904
|
var FS_MODULES = /* @__PURE__ */ new Set(["fs", "node:fs", "fs/promises", "node:fs/promises"]);
|
|
16488
16905
|
var FS_READERS = /* @__PURE__ */ new Set(["readFile", "readFileSync"]);
|
|
@@ -16551,28 +16968,28 @@ var SOURCE_COUPLED_TEST_DOCUMENTATION = {
|
|
|
16551
16968
|
]
|
|
16552
16969
|
};
|
|
16553
16970
|
function staticMemberName7(node) {
|
|
16554
|
-
if (!node.computed && node.property.type ===
|
|
16555
|
-
if (node.computed && node.property.type ===
|
|
16971
|
+
if (!node.computed && node.property.type === AST_NODE_TYPES71.Identifier) return node.property.name;
|
|
16972
|
+
if (node.computed && node.property.type === AST_NODE_TYPES71.Literal && typeof node.property.value === "string") return node.property.value;
|
|
16556
16973
|
return null;
|
|
16557
16974
|
}
|
|
16558
|
-
function
|
|
16559
|
-
if (node.type ===
|
|
16560
|
-
if (node.type ===
|
|
16561
|
-
if (node.type ===
|
|
16975
|
+
function unwrap6(node) {
|
|
16976
|
+
if (node.type === AST_NODE_TYPES71.AwaitExpression) return unwrap6(node.argument);
|
|
16977
|
+
if (node.type === AST_NODE_TYPES71.ChainExpression) return unwrap6(node.expression);
|
|
16978
|
+
if (node.type === AST_NODE_TYPES71.TSAsExpression || node.type === AST_NODE_TYPES71.TSNonNullExpression || node.type === AST_NODE_TYPES71.TSTypeAssertion) return unwrap6(node.expression);
|
|
16562
16979
|
return node;
|
|
16563
16980
|
}
|
|
16564
16981
|
function stringValue(node) {
|
|
16565
|
-
const current =
|
|
16566
|
-
if (current.type ===
|
|
16567
|
-
if (current.type ===
|
|
16982
|
+
const current = unwrap6(node);
|
|
16983
|
+
if (current.type === AST_NODE_TYPES71.Literal && typeof current.value === "string") return current.value;
|
|
16984
|
+
if (current.type === AST_NODE_TYPES71.TemplateLiteral && current.expressions.length === 0) return current.quasis[0]?.value.cooked ?? null;
|
|
16568
16985
|
return null;
|
|
16569
16986
|
}
|
|
16570
16987
|
function importSource(node) {
|
|
16571
16988
|
return typeof node.source.value === "string" ? node.source.value : null;
|
|
16572
16989
|
}
|
|
16573
16990
|
function requireSource(node) {
|
|
16574
|
-
const current =
|
|
16575
|
-
if (current.type !==
|
|
16991
|
+
const current = unwrap6(node);
|
|
16992
|
+
if (current.type !== AST_NODE_TYPES71.CallExpression || current.callee.type !== AST_NODE_TYPES71.Identifier || current.callee.name !== "require" || current.arguments.length !== 1 || current.arguments[0]?.type === AST_NODE_TYPES71.SpreadElement) return null;
|
|
16576
16993
|
return stringValue(current.arguments[0]);
|
|
16577
16994
|
}
|
|
16578
16995
|
function newScope() {
|
|
@@ -16609,80 +17026,80 @@ function createSourceCoupledRule(name, documentation, sourceSuffixRe) {
|
|
|
16609
17026
|
return /* @__PURE__ */ new Set();
|
|
16610
17027
|
};
|
|
16611
17028
|
const sourcePath = (node) => {
|
|
16612
|
-
const current =
|
|
17029
|
+
const current = unwrap6(node);
|
|
16613
17030
|
const value = stringValue(current);
|
|
16614
17031
|
if (value !== null) return sourceSuffixRe.test(value);
|
|
16615
|
-
if (current.type ===
|
|
16616
|
-
if (current.type ===
|
|
17032
|
+
if (current.type === AST_NODE_TYPES71.Identifier) return visible("paths", current.name);
|
|
17033
|
+
if (current.type === AST_NODE_TYPES71.BinaryExpression && current.operator === "+") {
|
|
16617
17034
|
return sourcePath(current.left) || sourcePath(current.right);
|
|
16618
17035
|
}
|
|
16619
|
-
if (current.type ===
|
|
16620
|
-
if (current.type ===
|
|
16621
|
-
return current.arguments.some((argument) => argument.type !==
|
|
17036
|
+
if (current.type === AST_NODE_TYPES71.TemplateLiteral) return current.expressions.some(sourcePath);
|
|
17037
|
+
if (current.type === AST_NODE_TYPES71.CallExpression || current.type === AST_NODE_TYPES71.NewExpression) {
|
|
17038
|
+
return current.arguments.some((argument) => argument.type !== AST_NODE_TYPES71.SpreadElement && sourcePath(argument));
|
|
16622
17039
|
}
|
|
16623
|
-
if (current.type ===
|
|
17040
|
+
if (current.type === AST_NODE_TYPES71.MemberExpression) return sourcePath(current.object);
|
|
16624
17041
|
return false;
|
|
16625
17042
|
};
|
|
16626
17043
|
const rawRead = (node) => {
|
|
16627
|
-
const current =
|
|
16628
|
-
if (current.type !==
|
|
16629
|
-
const callee =
|
|
16630
|
-
if (callee.type ===
|
|
17044
|
+
const current = unwrap6(node);
|
|
17045
|
+
if (current.type !== AST_NODE_TYPES71.CallExpression || current.arguments.length === 0) return false;
|
|
17046
|
+
const callee = unwrap6(current.callee);
|
|
17047
|
+
if (callee.type === AST_NODE_TYPES71.Identifier) {
|
|
16631
17048
|
return visible("fsReaders", callee.name) && sourcePath(current.arguments[0]);
|
|
16632
17049
|
}
|
|
16633
|
-
if (callee.type !==
|
|
17050
|
+
if (callee.type !== AST_NODE_TYPES71.MemberExpression) return false;
|
|
16634
17051
|
const name2 = staticMemberName7(callee);
|
|
16635
|
-
const object =
|
|
16636
|
-
return name2 !== null && FS_READERS.has(name2) && object.type ===
|
|
17052
|
+
const object = unwrap6(callee.object);
|
|
17053
|
+
return name2 !== null && FS_READERS.has(name2) && object.type === AST_NODE_TYPES71.Identifier && visible("fsObjects", object.name) && sourcePath(current.arguments[0]);
|
|
16637
17054
|
};
|
|
16638
17055
|
const rawOrigins = (node) => {
|
|
16639
|
-
const current =
|
|
16640
|
-
if (current.type ===
|
|
17056
|
+
const current = unwrap6(node);
|
|
17057
|
+
if (current.type === AST_NODE_TYPES71.Identifier) return visibleRawOrigins(current.name);
|
|
16641
17058
|
if (rawRead(current)) return /* @__PURE__ */ new Set([`${current.range[0]}:${current.range[1]}`]);
|
|
16642
|
-
if (current.type ===
|
|
16643
|
-
if (current.type ===
|
|
16644
|
-
if (current.type !==
|
|
16645
|
-
const callee =
|
|
16646
|
-
if (callee.type !==
|
|
17059
|
+
if (current.type === AST_NODE_TYPES71.BinaryExpression && current.operator === "+") return /* @__PURE__ */ new Set([...rawOrigins(current.left), ...rawOrigins(current.right)]);
|
|
17060
|
+
if (current.type === AST_NODE_TYPES71.MemberExpression && staticMemberName7(current) === "length") return rawOrigins(current.object);
|
|
17061
|
+
if (current.type !== AST_NODE_TYPES71.CallExpression) return /* @__PURE__ */ new Set();
|
|
17062
|
+
const callee = unwrap6(current.callee);
|
|
17063
|
+
if (callee.type !== AST_NODE_TYPES71.MemberExpression) return /* @__PURE__ */ new Set();
|
|
16647
17064
|
const name2 = staticMemberName7(callee);
|
|
16648
17065
|
return name2 !== null && TEXT_TRANSFORMS.has(name2) ? rawOrigins(callee.object) : /* @__PURE__ */ new Set();
|
|
16649
17066
|
};
|
|
16650
17067
|
const evidenceOrigins = (node) => {
|
|
16651
|
-
const current =
|
|
17068
|
+
const current = unwrap6(node);
|
|
16652
17069
|
const direct = rawOrigins(current);
|
|
16653
17070
|
if (direct.size > 0) return direct;
|
|
16654
|
-
if (current.type ===
|
|
16655
|
-
if (current.type ===
|
|
16656
|
-
if (current.type !==
|
|
16657
|
-
const callee =
|
|
16658
|
-
if (callee.type !==
|
|
17071
|
+
if (current.type === AST_NODE_TYPES71.BinaryExpression || current.type === AST_NODE_TYPES71.LogicalExpression) return /* @__PURE__ */ new Set([...evidenceOrigins(current.left), ...evidenceOrigins(current.right)]);
|
|
17072
|
+
if (current.type === AST_NODE_TYPES71.UnaryExpression) return evidenceOrigins(current.argument);
|
|
17073
|
+
if (current.type !== AST_NODE_TYPES71.CallExpression) return /* @__PURE__ */ new Set();
|
|
17074
|
+
const callee = unwrap6(current.callee);
|
|
17075
|
+
if (callee.type !== AST_NODE_TYPES71.MemberExpression) return /* @__PURE__ */ new Set();
|
|
16659
17076
|
const name2 = staticMemberName7(callee);
|
|
16660
17077
|
if (name2 !== null && TEXT_PREDICATES.has(name2)) return rawOrigins(callee.object);
|
|
16661
|
-
if (name2 !== null && REGEXP_PREDICATES.has(name2)) return new Set(current.arguments.flatMap((argument) => argument.type ===
|
|
17078
|
+
if (name2 !== null && REGEXP_PREDICATES.has(name2)) return new Set(current.arguments.flatMap((argument) => argument.type === AST_NODE_TYPES71.SpreadElement ? [] : [...rawOrigins(argument)]));
|
|
16662
17079
|
return /* @__PURE__ */ new Set();
|
|
16663
17080
|
};
|
|
16664
17081
|
const rawAssertionOrigins = (node) => {
|
|
16665
|
-
const callee =
|
|
16666
|
-
if (callee.type ===
|
|
16667
|
-
return new Set(node.arguments.flatMap((argument) => argument.type ===
|
|
17082
|
+
const callee = unwrap6(node.callee);
|
|
17083
|
+
if (callee.type === AST_NODE_TYPES71.Identifier && callee.name === "assert") {
|
|
17084
|
+
return new Set(node.arguments.flatMap((argument) => argument.type === AST_NODE_TYPES71.SpreadElement ? [] : [...evidenceOrigins(argument)]));
|
|
16668
17085
|
}
|
|
16669
|
-
if (callee.type !==
|
|
17086
|
+
if (callee.type !== AST_NODE_TYPES71.MemberExpression) return /* @__PURE__ */ new Set();
|
|
16670
17087
|
const matcher = staticMemberName7(callee);
|
|
16671
17088
|
if (matcher === null) return /* @__PURE__ */ new Set();
|
|
16672
|
-
let receiver =
|
|
16673
|
-
while (receiver.type ===
|
|
16674
|
-
if (receiver.type ===
|
|
17089
|
+
let receiver = unwrap6(callee.object);
|
|
17090
|
+
while (receiver.type === AST_NODE_TYPES71.MemberExpression && EXPECT_MODIFIERS2.has(staticMemberName7(receiver) ?? "")) receiver = unwrap6(receiver.object);
|
|
17091
|
+
if (receiver.type === AST_NODE_TYPES71.CallExpression && receiver.callee.type === AST_NODE_TYPES71.Identifier && receiver.callee.name === "expect") {
|
|
16675
17092
|
if (!EXPECT_MATCHERS.has(matcher)) return /* @__PURE__ */ new Set();
|
|
16676
|
-
return new Set([...receiver.arguments, ...node.arguments].flatMap((argument) => argument.type ===
|
|
17093
|
+
return new Set([...receiver.arguments, ...node.arguments].flatMap((argument) => argument.type === AST_NODE_TYPES71.SpreadElement ? [] : [...evidenceOrigins(argument)]));
|
|
16677
17094
|
}
|
|
16678
|
-
if (receiver.type !==
|
|
16679
|
-
return new Set(node.arguments.flatMap((argument) => argument.type ===
|
|
17095
|
+
if (receiver.type !== AST_NODE_TYPES71.Identifier || receiver.name !== "assert" || !ASSERT_MATCHERS.has(matcher)) return /* @__PURE__ */ new Set();
|
|
17096
|
+
return new Set(node.arguments.flatMap((argument) => argument.type === AST_NODE_TYPES71.SpreadElement ? [] : [...evidenceOrigins(argument)]));
|
|
16680
17097
|
};
|
|
16681
17098
|
const rawRegexExtractionOrigins = (node) => {
|
|
16682
|
-
const callee =
|
|
16683
|
-
if (callee.type !==
|
|
17099
|
+
const callee = unwrap6(node.callee);
|
|
17100
|
+
if (callee.type !== AST_NODE_TYPES71.MemberExpression || staticMemberName7(callee) !== "matchAll" || node.arguments.length !== 1) return /* @__PURE__ */ new Set();
|
|
16684
17101
|
const argument = node.arguments[0];
|
|
16685
|
-
if (argument?.type !==
|
|
17102
|
+
if (argument?.type !== AST_NODE_TYPES71.Literal || !(argument.value instanceof RegExp)) return /* @__PURE__ */ new Set();
|
|
16686
17103
|
return rawOrigins(callee.object);
|
|
16687
17104
|
};
|
|
16688
17105
|
const declare = (name2, state) => {
|
|
@@ -16702,16 +17119,16 @@ function createSourceCoupledRule(name, documentation, sourceSuffixRe) {
|
|
|
16702
17119
|
}
|
|
16703
17120
|
};
|
|
16704
17121
|
const sourceCollection = (node) => {
|
|
16705
|
-
const current =
|
|
16706
|
-
return current.type ===
|
|
17122
|
+
const current = unwrap6(node);
|
|
17123
|
+
return current.type === AST_NODE_TYPES71.ArrayExpression && current.elements.length > 0 && current.elements.every((element) => element !== null && element.type !== AST_NODE_TYPES71.SpreadElement && sourcePath(element));
|
|
16707
17124
|
};
|
|
16708
17125
|
const declaredNames2 = (node) => {
|
|
16709
|
-
const current =
|
|
16710
|
-
if (current.type ===
|
|
16711
|
-
if (current.type ===
|
|
16712
|
-
if (current.type ===
|
|
16713
|
-
if (current.type ===
|
|
16714
|
-
if (current.type ===
|
|
17126
|
+
const current = unwrap6(node);
|
|
17127
|
+
if (current.type === AST_NODE_TYPES71.Identifier) return [current.name];
|
|
17128
|
+
if (current.type === AST_NODE_TYPES71.AssignmentPattern) return declaredNames2(current.left);
|
|
17129
|
+
if (current.type === AST_NODE_TYPES71.RestElement) return declaredNames2(current.argument);
|
|
17130
|
+
if (current.type === AST_NODE_TYPES71.ArrayPattern) return current.elements.flatMap((element) => element === null ? [] : declaredNames2(element));
|
|
17131
|
+
if (current.type === AST_NODE_TYPES71.ObjectPattern) return current.properties.flatMap((property) => property.type === AST_NODE_TYPES71.RestElement ? declaredNames2(property.argument) : declaredNames2(property.value));
|
|
16715
17132
|
return [];
|
|
16716
17133
|
};
|
|
16717
17134
|
const enterFunction = (node) => {
|
|
@@ -16726,8 +17143,8 @@ function createSourceCoupledRule(name, documentation, sourceSuffixRe) {
|
|
|
16726
17143
|
const source = importSource(node);
|
|
16727
17144
|
if (source === null || !FS_MODULES.has(source)) return;
|
|
16728
17145
|
for (const specifier of node.specifiers) {
|
|
16729
|
-
if (specifier.type ===
|
|
16730
|
-
const imported = specifier.imported.type ===
|
|
17146
|
+
if (specifier.type === AST_NODE_TYPES71.ImportSpecifier) {
|
|
17147
|
+
const imported = specifier.imported.type === AST_NODE_TYPES71.Identifier ? specifier.imported.name : String(specifier.imported.value);
|
|
16731
17148
|
if (FS_READERS.has(imported)) declare(specifier.local.name, { fsReader: true });
|
|
16732
17149
|
} else {
|
|
16733
17150
|
declare(specifier.local.name, { fsObject: true });
|
|
@@ -16739,29 +17156,29 @@ function createSourceCoupledRule(name, documentation, sourceSuffixRe) {
|
|
|
16739
17156
|
VariableDeclarator(node) {
|
|
16740
17157
|
if (node.init === null) return;
|
|
16741
17158
|
const required = requireSource(node.init);
|
|
16742
|
-
if (required !== null && FS_MODULES.has(required) && node.id.type ===
|
|
17159
|
+
if (required !== null && FS_MODULES.has(required) && node.id.type === AST_NODE_TYPES71.Identifier) {
|
|
16743
17160
|
declare(node.id.name, { fsObject: true });
|
|
16744
17161
|
return;
|
|
16745
17162
|
}
|
|
16746
|
-
if (node.id.type ===
|
|
17163
|
+
if (node.id.type === AST_NODE_TYPES71.ObjectPattern && required !== null && FS_MODULES.has(required)) {
|
|
16747
17164
|
for (const property of node.id.properties) {
|
|
16748
|
-
if (property.type !==
|
|
16749
|
-
const key = property.key.type ===
|
|
17165
|
+
if (property.type !== AST_NODE_TYPES71.Property || property.value.type !== AST_NODE_TYPES71.Identifier) continue;
|
|
17166
|
+
const key = property.key.type === AST_NODE_TYPES71.Identifier ? property.key.name : property.key.type === AST_NODE_TYPES71.Literal ? String(property.key.value) : "";
|
|
16750
17167
|
if (FS_READERS.has(key)) declare(property.value.name, { fsReader: true });
|
|
16751
17168
|
}
|
|
16752
17169
|
return;
|
|
16753
17170
|
}
|
|
16754
|
-
if (node.id.type !==
|
|
17171
|
+
if (node.id.type !== AST_NODE_TYPES71.Identifier) return;
|
|
16755
17172
|
declare(node.id.name, { collection: sourceCollection(node.init), path: sourcePath(node.init), rawOrigins: rawOrigins(node.init) });
|
|
16756
17173
|
},
|
|
16757
17174
|
AssignmentExpression(node) {
|
|
16758
|
-
if (node.left.type ===
|
|
17175
|
+
if (node.left.type === AST_NODE_TYPES71.Identifier) declare(node.left.name, { path: sourcePath(node.right), rawOrigins: rawOrigins(node.right) });
|
|
16759
17176
|
},
|
|
16760
17177
|
ForOfStatement(node) {
|
|
16761
|
-
const right =
|
|
16762
|
-
const collection = right.type ===
|
|
16763
|
-
const left = node.left.type ===
|
|
16764
|
-
if (collection && left?.type ===
|
|
17178
|
+
const right = unwrap6(node.right);
|
|
17179
|
+
const collection = right.type === AST_NODE_TYPES71.Identifier && visible("collections", right.name);
|
|
17180
|
+
const left = node.left.type === AST_NODE_TYPES71.VariableDeclaration ? node.left.declarations[0]?.id : node.left;
|
|
17181
|
+
if (collection && left?.type === AST_NODE_TYPES71.Identifier) declare(left.name, { path: true });
|
|
16765
17182
|
},
|
|
16766
17183
|
CallExpression(node) {
|
|
16767
17184
|
const origins = /* @__PURE__ */ new Set([
|
|
@@ -16782,6 +17199,128 @@ var source_coupled_test_default = createSourceCoupledRule(
|
|
|
16782
17199
|
GENERAL_SOURCE_SUFFIX_RE
|
|
16783
17200
|
);
|
|
16784
17201
|
|
|
17202
|
+
// src/rules/sole-export-matches-filename.ts
|
|
17203
|
+
import { AST_NODE_TYPES as AST_NODE_TYPES72 } from "@typescript-eslint/utils";
|
|
17204
|
+
var SOLE_EXPORT_MATCHES_FILENAME_DOCUMENTATION = {
|
|
17205
|
+
summary: "Match a module filename to its sole named public runtime export.",
|
|
17206
|
+
rationale: "When a module owns one runtime responsibility, matching names make that responsibility directly discoverable.",
|
|
17207
|
+
remediation: "Rename the module stem to the kebab-case export name, or colocate genuinely related exports.",
|
|
17208
|
+
category: "maintainability",
|
|
17209
|
+
limitations: [
|
|
17210
|
+
"Framework entrypoints, generic stems covered by no-generic-single-export-module, tests, generated files, anonymous defaults, CommonJS, and re-exports are excluded.",
|
|
17211
|
+
"The rule compares the primary filename stem and preserves conventional suffixes such as .server or .worker."
|
|
17212
|
+
],
|
|
17213
|
+
examples: [
|
|
17214
|
+
{ id: "matching-class", title: "Match a class and module", outcome: "no-match", files: [{ path: "src/artifact-store.ts", source: "export class ArtifactStore {}" }], focusPath: "src/artifact-store.ts", expectedCount: 0, public: true },
|
|
17215
|
+
{ id: "mismatched-class", title: "Do not hide a sole class behind another filename", outcome: "match", files: [{ path: "src/artifacts.ts", source: "export class ArtifactStore {}" }], focusPath: "src/artifacts.ts", expectedCount: 1, public: true }
|
|
17216
|
+
]
|
|
17217
|
+
};
|
|
17218
|
+
var EXCLUDED_STEMS = /* @__PURE__ */ new Set([
|
|
17219
|
+
"common",
|
|
17220
|
+
"config",
|
|
17221
|
+
"constants",
|
|
17222
|
+
"error",
|
|
17223
|
+
"errors",
|
|
17224
|
+
"global",
|
|
17225
|
+
"handler",
|
|
17226
|
+
"helpers",
|
|
17227
|
+
"index",
|
|
17228
|
+
"layout",
|
|
17229
|
+
"loading",
|
|
17230
|
+
"middleware",
|
|
17231
|
+
"misc",
|
|
17232
|
+
"models",
|
|
17233
|
+
"not-found",
|
|
17234
|
+
"page",
|
|
17235
|
+
"route",
|
|
17236
|
+
"schema",
|
|
17237
|
+
"shared",
|
|
17238
|
+
"template",
|
|
17239
|
+
"types",
|
|
17240
|
+
"util",
|
|
17241
|
+
"utils",
|
|
17242
|
+
"worker"
|
|
17243
|
+
]);
|
|
17244
|
+
function stem3(filename) {
|
|
17245
|
+
const base = filename.replaceAll("\\", "/").split("/").at(-1) ?? "";
|
|
17246
|
+
return base.replace(/\.[cm]?[jt]sx?$/u, "").split(".")[0] ?? "";
|
|
17247
|
+
}
|
|
17248
|
+
function kebabCase(name) {
|
|
17249
|
+
return name.replace(/([A-Z]{2,})([A-Z][a-z])/gu, "$1-$2").replace(/([a-z0-9])([A-Z])/gu, "$1-$2").replaceAll(/[^a-z0-9]+/giu, "-").replaceAll(/^-+|-+$/gu, "").toLowerCase();
|
|
17250
|
+
}
|
|
17251
|
+
function declarationExport(statement) {
|
|
17252
|
+
const declaration = statement.declaration;
|
|
17253
|
+
if (declaration === null || declaration.declare === true) return [];
|
|
17254
|
+
if (declaration.type === AST_NODE_TYPES72.ClassDeclaration || declaration.type === AST_NODE_TYPES72.FunctionDeclaration || declaration.type === AST_NODE_TYPES72.TSEnumDeclaration) return declaration.id === null ? [] : [{ name: declaration.id.name, node: declaration }];
|
|
17255
|
+
if (declaration.type !== AST_NODE_TYPES72.VariableDeclaration) return [];
|
|
17256
|
+
return declaration.declarations.flatMap(
|
|
17257
|
+
(item) => item.id.type === AST_NODE_TYPES72.Identifier ? [{ name: item.id.name, node: item }] : []
|
|
17258
|
+
);
|
|
17259
|
+
}
|
|
17260
|
+
var sole_export_matches_filename_default = createRule({
|
|
17261
|
+
name: "sole-export-matches-filename",
|
|
17262
|
+
documentation: SOLE_EXPORT_MATCHES_FILENAME_DOCUMENTATION,
|
|
17263
|
+
meta: {
|
|
17264
|
+
type: "suggestion",
|
|
17265
|
+
docs: { description: "Match a module filename to its sole named public runtime export." },
|
|
17266
|
+
schema: [],
|
|
17267
|
+
messages: {
|
|
17268
|
+
matchSoleExport: "This module's sole runtime export is `{{exported}}`; rename the file stem to `{{expected}}`."
|
|
17269
|
+
}
|
|
17270
|
+
},
|
|
17271
|
+
defaultOptions: [],
|
|
17272
|
+
create(context) {
|
|
17273
|
+
const fileStem = stem3(context.filename);
|
|
17274
|
+
const normalizedFilename = context.filename.replaceAll("\\", "/");
|
|
17275
|
+
if (EXCLUDED_STEMS.has(fileStem) || normalizedFilename.includes("/pages/") || context.filename.endsWith(".d.ts") || isTestFile(context.filename) || isGeneratedFile(context.filename, context.sourceCode.text)) return {};
|
|
17276
|
+
return {
|
|
17277
|
+
"Program:exit"(program) {
|
|
17278
|
+
const exports = [];
|
|
17279
|
+
const publicExports = /* @__PURE__ */ new Set();
|
|
17280
|
+
for (const statement of program.body) {
|
|
17281
|
+
if (statement.type === AST_NODE_TYPES72.ExportAllDeclaration || statement.type === AST_NODE_TYPES72.ExportNamedDeclaration && statement.source !== null) return;
|
|
17282
|
+
if (statement.type === AST_NODE_TYPES72.ExportDefaultDeclaration) {
|
|
17283
|
+
publicExports.add("default");
|
|
17284
|
+
const declaration2 = statement.declaration;
|
|
17285
|
+
if ((declaration2.type === AST_NODE_TYPES72.ClassDeclaration || declaration2.type === AST_NODE_TYPES72.FunctionDeclaration) && declaration2.id !== null) exports.push({ name: declaration2.id.name, node: declaration2 });
|
|
17286
|
+
else return;
|
|
17287
|
+
}
|
|
17288
|
+
if (statement.type !== AST_NODE_TYPES72.ExportNamedDeclaration) continue;
|
|
17289
|
+
const declaration = statement.declaration;
|
|
17290
|
+
if (declaration !== null && "id" in declaration && declaration.id?.type === AST_NODE_TYPES72.Identifier) {
|
|
17291
|
+
publicExports.add(declaration.id.name);
|
|
17292
|
+
}
|
|
17293
|
+
if (declaration?.type === AST_NODE_TYPES72.VariableDeclaration) {
|
|
17294
|
+
for (const item of declaration.declarations) {
|
|
17295
|
+
if (item.id.type === AST_NODE_TYPES72.Identifier) publicExports.add(item.id.name);
|
|
17296
|
+
}
|
|
17297
|
+
}
|
|
17298
|
+
for (const specifier of statement.specifiers) {
|
|
17299
|
+
const exported = specifier.exported.type === AST_NODE_TYPES72.Identifier ? specifier.exported.name : specifier.exported.value;
|
|
17300
|
+
publicExports.add(String(exported));
|
|
17301
|
+
}
|
|
17302
|
+
if (statement.exportKind === "type") continue;
|
|
17303
|
+
exports.push(...declarationExport(statement));
|
|
17304
|
+
for (const specifier of statement.specifiers) {
|
|
17305
|
+
const exported = specifier.exported.type === AST_NODE_TYPES72.Identifier ? specifier.exported.name : specifier.exported.value;
|
|
17306
|
+
publicExports.add(String(exported));
|
|
17307
|
+
if (specifier.exportKind === "type") continue;
|
|
17308
|
+
if (exported === "default") exports.push({ name: specifier.local.name, node: specifier });
|
|
17309
|
+
else exports.push({ name: String(exported), node: specifier });
|
|
17310
|
+
}
|
|
17311
|
+
}
|
|
17312
|
+
const unique = new Map(exports.map((item) => [item.name, item]));
|
|
17313
|
+
if (unique.size !== 1 || publicExports.size !== 1) return;
|
|
17314
|
+
const only = [...unique.values()][0];
|
|
17315
|
+
if (only === void 0) return;
|
|
17316
|
+
const expected = kebabCase(only.name);
|
|
17317
|
+
if (expected === "" || expected === fileStem.toLowerCase()) return;
|
|
17318
|
+
context.report({ node: only.node, messageId: "matchSoleExport", data: { exported: only.name, expected } });
|
|
17319
|
+
}
|
|
17320
|
+
};
|
|
17321
|
+
}
|
|
17322
|
+
});
|
|
17323
|
+
|
|
16785
17324
|
// src/rules/iac-source-coupled-test.ts
|
|
16786
17325
|
var IAC_SOURCE_SUFFIX_RE = /(?:\.tf\.json|\.tftest\.(?:hcl|json)|\.(?:hcl|tf|tfvars))$/iu;
|
|
16787
17326
|
var IAC_SOURCE_COUPLED_TEST_DOCUMENTATION = {
|
|
@@ -16822,7 +17361,7 @@ var iac_source_coupled_test_default = createSourceCoupledRule(
|
|
|
16822
17361
|
|
|
16823
17362
|
// src/rules/require-pascal-case-zod-schema-name.ts
|
|
16824
17363
|
import {
|
|
16825
|
-
AST_NODE_TYPES as
|
|
17364
|
+
AST_NODE_TYPES as AST_NODE_TYPES73,
|
|
16826
17365
|
ASTUtils as ASTUtils23
|
|
16827
17366
|
} from "@typescript-eslint/utils";
|
|
16828
17367
|
var REQUIRE_PASCAL_CASE_ZOD_SCHEMA_NAME_DOCUMENTATION = {
|
|
@@ -16956,18 +17495,18 @@ var SCHEMA_RETURNING_METHODS = /* @__PURE__ */ new Set([
|
|
|
16956
17495
|
"superRefine",
|
|
16957
17496
|
"transform"
|
|
16958
17497
|
]);
|
|
16959
|
-
var terminalMethodName = (callee) => !callee.computed && callee.property.type ===
|
|
17498
|
+
var terminalMethodName = (callee) => !callee.computed && callee.property.type === AST_NODE_TYPES73.Identifier ? callee.property.name : null;
|
|
16960
17499
|
var calleeChainRoot = (node) => {
|
|
16961
17500
|
let current = node;
|
|
16962
17501
|
for (; ; ) {
|
|
16963
|
-
if (current.type ===
|
|
17502
|
+
if (current.type === AST_NODE_TYPES73.Identifier) {
|
|
16964
17503
|
return current;
|
|
16965
17504
|
}
|
|
16966
|
-
if (current.type ===
|
|
17505
|
+
if (current.type === AST_NODE_TYPES73.MemberExpression) {
|
|
16967
17506
|
current = current.object;
|
|
16968
17507
|
continue;
|
|
16969
17508
|
}
|
|
16970
|
-
if (current.type ===
|
|
17509
|
+
if (current.type === AST_NODE_TYPES73.CallExpression) {
|
|
16971
17510
|
current = current.callee;
|
|
16972
17511
|
continue;
|
|
16973
17512
|
}
|
|
@@ -16978,13 +17517,13 @@ var chainMemberNames = (node) => {
|
|
|
16978
17517
|
const names = [];
|
|
16979
17518
|
let current = node;
|
|
16980
17519
|
for (; ; ) {
|
|
16981
|
-
if (current.type ===
|
|
16982
|
-
if (current.computed || current.property.type !==
|
|
17520
|
+
if (current.type === AST_NODE_TYPES73.MemberExpression) {
|
|
17521
|
+
if (current.computed || current.property.type !== AST_NODE_TYPES73.Identifier) return [];
|
|
16983
17522
|
names.push(current.property.name);
|
|
16984
17523
|
current = current.object;
|
|
16985
17524
|
continue;
|
|
16986
17525
|
}
|
|
16987
|
-
if (current.type ===
|
|
17526
|
+
if (current.type === AST_NODE_TYPES73.CallExpression) {
|
|
16988
17527
|
current = current.callee;
|
|
16989
17528
|
continue;
|
|
16990
17529
|
}
|
|
@@ -16995,16 +17534,16 @@ var chainMemberNames = (node) => {
|
|
|
16995
17534
|
};
|
|
16996
17535
|
var unwrapExpression4 = (node) => {
|
|
16997
17536
|
let current = node;
|
|
16998
|
-
while (current.type ===
|
|
17537
|
+
while (current.type === AST_NODE_TYPES73.TSAsExpression || current.type === AST_NODE_TYPES73.TSSatisfiesExpression || current.type === AST_NODE_TYPES73.TSNonNullExpression || current.type === AST_NODE_TYPES73.TSTypeAssertion) {
|
|
16999
17538
|
current = current.expression;
|
|
17000
17539
|
}
|
|
17001
17540
|
return current;
|
|
17002
17541
|
};
|
|
17003
17542
|
var isModuleDeclarator = (node) => {
|
|
17004
17543
|
const declaration = node.parent;
|
|
17005
|
-
if (declaration.type !==
|
|
17544
|
+
if (declaration.type !== AST_NODE_TYPES73.VariableDeclaration) return false;
|
|
17006
17545
|
const owner = declaration.parent;
|
|
17007
|
-
return owner.type ===
|
|
17546
|
+
return owner.type === AST_NODE_TYPES73.Program || owner.type === AST_NODE_TYPES73.ExportNamedDeclaration && owner.parent.type === AST_NODE_TYPES73.Program;
|
|
17008
17547
|
};
|
|
17009
17548
|
var require_pascal_case_zod_schema_name_default = createRule({
|
|
17010
17549
|
name: "require-pascal-case-zod-schema-name",
|
|
@@ -17045,8 +17584,8 @@ var require_pascal_case_zod_schema_name_default = createRule({
|
|
|
17045
17584
|
}
|
|
17046
17585
|
function isConfirmedSchema(expression) {
|
|
17047
17586
|
const init = unwrapExpression4(expression);
|
|
17048
|
-
if (init.type ===
|
|
17049
|
-
if (init.type !==
|
|
17587
|
+
if (init.type === AST_NODE_TYPES73.Identifier) return isSchemaBinding(init);
|
|
17588
|
+
if (init.type !== AST_NODE_TYPES73.CallExpression || init.callee.type !== AST_NODE_TYPES73.MemberExpression) {
|
|
17050
17589
|
return false;
|
|
17051
17590
|
}
|
|
17052
17591
|
const terminal = terminalMethodName(init.callee);
|
|
@@ -17066,7 +17605,7 @@ var require_pascal_case_zod_schema_name_default = createRule({
|
|
|
17066
17605
|
ImportDeclaration(node) {
|
|
17067
17606
|
if (!isZodModule(node.source.value)) return;
|
|
17068
17607
|
for (const specifier of node.specifiers) {
|
|
17069
|
-
if (specifier.type ===
|
|
17608
|
+
if (specifier.type === AST_NODE_TYPES73.ImportNamespaceSpecifier || specifier.type === AST_NODE_TYPES73.ImportDefaultSpecifier || specifier.type === AST_NODE_TYPES73.ImportSpecifier && (specifier.imported.type === AST_NODE_TYPES73.Identifier ? specifier.imported.name === "z" : specifier.imported.value === "z")) {
|
|
17070
17609
|
recordZodBinding(specifier.local);
|
|
17071
17610
|
}
|
|
17072
17611
|
}
|
|
@@ -17075,7 +17614,7 @@ var require_pascal_case_zod_schema_name_default = createRule({
|
|
|
17075
17614
|
if (!isModuleDeclarator(node)) return;
|
|
17076
17615
|
const init = node.init;
|
|
17077
17616
|
if (init === null || init === void 0) return;
|
|
17078
|
-
if (node.id.type !==
|
|
17617
|
+
if (node.id.type !== AST_NODE_TYPES73.Identifier) return;
|
|
17079
17618
|
if (!isConfirmedSchema(init)) return;
|
|
17080
17619
|
const binding = resolvedBinding(node.id);
|
|
17081
17620
|
if (binding !== null) schemaBindings.add(binding);
|
|
@@ -17233,11 +17772,16 @@ var RULES = {
|
|
|
17233
17772
|
"prefer-shadcn-primitives": prefer_shadcn_primitives_default,
|
|
17234
17773
|
"prefer-module-level-constant": prefer_module_level_constant_default,
|
|
17235
17774
|
"prefer-module-level-schema": prefer_module_level_schema_default,
|
|
17775
|
+
"prefer-named-complex-return-type": prefer_named_complex_return_type_default,
|
|
17236
17776
|
"prefer-native-random-uuid": prefer_native_random_uuid_default,
|
|
17777
|
+
"prefer-node-crypto-hash": prefer_node_crypto_hash_default,
|
|
17778
|
+
"prefer-node-fs-promises": prefer_node_fs_promises_default,
|
|
17237
17779
|
"prefer-non-nullable-collection": prefer_non_nullable_collection_default,
|
|
17238
17780
|
"prefer-nullish-filter-predicate": prefer_nullish_filter_predicate_default,
|
|
17239
17781
|
"prefer-await-in-async-return": prefer_await_in_async_return_default,
|
|
17240
17782
|
"prefer-schema-for-api-payload": prefer_schema_for_api_payload_default,
|
|
17783
|
+
"prefer-shared-zod-enum": prefer_shared_zod_enum_default,
|
|
17784
|
+
"prefer-switch-for-repeated-equality": prefer_switch_for_repeated_equality_default,
|
|
17241
17785
|
"prefer-semantic-colors": prefer_semantic_colors_default,
|
|
17242
17786
|
"prefer-server-actions": prefer_server_actions_default,
|
|
17243
17787
|
"prefer-whole-object-assertion": prefer_whole_object_assertion_default,
|
|
@@ -17246,23 +17790,33 @@ var RULES = {
|
|
|
17246
17790
|
"require-assert-never": require_assert_never_default,
|
|
17247
17791
|
"require-fetch-timeout": require_fetch_timeout_default,
|
|
17248
17792
|
"require-port-for-service": require_port_for_service_default,
|
|
17793
|
+
"require-sql-access-class": require_sql_access_class_default,
|
|
17249
17794
|
"require-static-next-matcher": require_static_next_matcher_default,
|
|
17250
17795
|
"require-zod-form-validation": require_zod_form_validation_default,
|
|
17251
17796
|
"store-insert-requires-on-conflict": store_insert_requires_on_conflict_default,
|
|
17252
17797
|
"stepdown": stepdown_default,
|
|
17253
17798
|
"source-coupled-test": source_coupled_test_default,
|
|
17799
|
+
"sole-export-matches-filename": sole_export_matches_filename_default,
|
|
17254
17800
|
"require-pascal-case-zod-schema-name": require_pascal_case_zod_schema_name_default
|
|
17255
17801
|
};
|
|
17256
17802
|
var meta = {
|
|
17257
17803
|
name: "@sarj/eslint-plugin",
|
|
17258
|
-
version: "15.
|
|
17804
|
+
version: "15.15.0"
|
|
17259
17805
|
};
|
|
17260
17806
|
var APPLICATION_ONLY_RULES = [
|
|
17261
17807
|
"no-restricted-library-load",
|
|
17262
17808
|
"prefer-native-random-uuid",
|
|
17263
17809
|
"prefer-shadcn-primitives"
|
|
17264
17810
|
];
|
|
17265
|
-
var ADVISORY_RULES = [
|
|
17811
|
+
var ADVISORY_RULES = [
|
|
17812
|
+
"@sarj/prefer-named-complex-return-type",
|
|
17813
|
+
"@sarj/prefer-node-crypto-hash",
|
|
17814
|
+
"@sarj/prefer-shared-zod-enum",
|
|
17815
|
+
"@sarj/prefer-switch-for-repeated-equality",
|
|
17816
|
+
"@sarj/require-pascal-case-zod-schema-name",
|
|
17817
|
+
"@sarj/require-sql-access-class",
|
|
17818
|
+
"@sarj/sole-export-matches-filename"
|
|
17819
|
+
];
|
|
17266
17820
|
var RECOMMENDED_RULES = {
|
|
17267
17821
|
"@sarj/interface-contract-members-private": "error",
|
|
17268
17822
|
"@sarj/iac-source-coupled-test": "error",
|
|
@@ -17316,10 +17870,15 @@ var RECOMMENDED_RULES = {
|
|
|
17316
17870
|
"@sarj/prefer-immutable-module-constant": "error",
|
|
17317
17871
|
"@sarj/prefer-module-level-constant": "error",
|
|
17318
17872
|
"@sarj/prefer-module-level-schema": "error",
|
|
17873
|
+
"@sarj/prefer-named-complex-return-type": "warn",
|
|
17874
|
+
"@sarj/prefer-node-crypto-hash": "warn",
|
|
17875
|
+
"@sarj/prefer-node-fs-promises": "error",
|
|
17319
17876
|
"@sarj/prefer-non-nullable-collection": "error",
|
|
17320
17877
|
"@sarj/prefer-nullish-filter-predicate": "error",
|
|
17321
17878
|
"@sarj/prefer-await-in-async-return": "error",
|
|
17322
17879
|
"@sarj/prefer-schema-for-api-payload": "error",
|
|
17880
|
+
"@sarj/prefer-shared-zod-enum": "warn",
|
|
17881
|
+
"@sarj/prefer-switch-for-repeated-equality": "warn",
|
|
17323
17882
|
"@sarj/prefer-semantic-colors": ["error", { requireSemanticTokens: true }],
|
|
17324
17883
|
"@sarj/prefer-server-actions": "error",
|
|
17325
17884
|
"@sarj/prefer-whole-object-assertion": "error",
|
|
@@ -17328,6 +17887,7 @@ var RECOMMENDED_RULES = {
|
|
|
17328
17887
|
"@sarj/require-assert-never": "error",
|
|
17329
17888
|
"@sarj/require-fetch-timeout": "error",
|
|
17330
17889
|
"@sarj/require-port-for-service": "error",
|
|
17890
|
+
"@sarj/require-sql-access-class": "warn",
|
|
17331
17891
|
"@sarj/require-static-next-matcher": "error",
|
|
17332
17892
|
"@sarj/require-use-form-default-values": "error",
|
|
17333
17893
|
"@sarj/require-use-server-in-actions-file": "error",
|
|
@@ -17335,6 +17895,7 @@ var RECOMMENDED_RULES = {
|
|
|
17335
17895
|
"@sarj/store-insert-requires-on-conflict": "error",
|
|
17336
17896
|
"@sarj/stepdown": "error",
|
|
17337
17897
|
"@sarj/source-coupled-test": "error",
|
|
17898
|
+
"@sarj/sole-export-matches-filename": "warn",
|
|
17338
17899
|
"@sarj/test-phase-label-comment": "error",
|
|
17339
17900
|
"@sarj/require-pascal-case-zod-schema-name": "warn"
|
|
17340
17901
|
};
|
|
@@ -17395,10 +17956,15 @@ var STRICT_RULES = {
|
|
|
17395
17956
|
"@sarj/prefer-immutable-module-constant": "error",
|
|
17396
17957
|
"@sarj/prefer-module-level-constant": "error",
|
|
17397
17958
|
"@sarj/prefer-module-level-schema": "error",
|
|
17959
|
+
"@sarj/prefer-named-complex-return-type": "warn",
|
|
17960
|
+
"@sarj/prefer-node-crypto-hash": "warn",
|
|
17961
|
+
"@sarj/prefer-node-fs-promises": "error",
|
|
17398
17962
|
"@sarj/prefer-non-nullable-collection": "error",
|
|
17399
17963
|
"@sarj/prefer-nullish-filter-predicate": "error",
|
|
17400
17964
|
"@sarj/prefer-await-in-async-return": "error",
|
|
17401
17965
|
"@sarj/prefer-schema-for-api-payload": "error",
|
|
17966
|
+
"@sarj/prefer-shared-zod-enum": "warn",
|
|
17967
|
+
"@sarj/prefer-switch-for-repeated-equality": "warn",
|
|
17402
17968
|
"@sarj/prefer-semantic-colors": ["error", { requireSemanticTokens: true }],
|
|
17403
17969
|
"@sarj/prefer-server-actions": "error",
|
|
17404
17970
|
"@sarj/prefer-whole-object-assertion": "error",
|
|
@@ -17407,6 +17973,7 @@ var STRICT_RULES = {
|
|
|
17407
17973
|
"@sarj/require-assert-never": "error",
|
|
17408
17974
|
"@sarj/require-fetch-timeout": "error",
|
|
17409
17975
|
"@sarj/require-port-for-service": "error",
|
|
17976
|
+
"@sarj/require-sql-access-class": "warn",
|
|
17410
17977
|
"@sarj/require-static-next-matcher": "error",
|
|
17411
17978
|
"@sarj/require-use-form-default-values": "error",
|
|
17412
17979
|
"@sarj/require-use-server-in-actions-file": "error",
|
|
@@ -17414,6 +17981,7 @@ var STRICT_RULES = {
|
|
|
17414
17981
|
"@sarj/store-insert-requires-on-conflict": "error",
|
|
17415
17982
|
"@sarj/stepdown": "error",
|
|
17416
17983
|
"@sarj/source-coupled-test": "error",
|
|
17984
|
+
"@sarj/sole-export-matches-filename": "warn",
|
|
17417
17985
|
"@sarj/test-phase-label-comment": "error",
|
|
17418
17986
|
"@sarj/require-pascal-case-zod-schema-name": "warn"
|
|
17419
17987
|
};
|