@sarj/eslint-plugin 15.13.3 → 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 +1395 -668
- package/dist/index.d.cts +35 -3
- package/dist/index.d.ts +35 -3
- package/dist/index.js +1398 -667
- 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 = {
|
|
@@ -12008,13 +12198,173 @@ var prefer_non_nullable_collection_default = createRule({
|
|
|
12008
12198
|
}
|
|
12009
12199
|
});
|
|
12010
12200
|
|
|
12011
|
-
// src/rules/prefer-
|
|
12201
|
+
// src/rules/prefer-nullish-filter-predicate.ts
|
|
12012
12202
|
import {
|
|
12203
|
+
AST_NODE_TYPES as AST_NODE_TYPES55,
|
|
12013
12204
|
ASTUtils as ASTUtils16,
|
|
12014
|
-
ESLintUtils as ESLintUtils5
|
|
12015
|
-
|
|
12205
|
+
ESLintUtils as ESLintUtils5
|
|
12206
|
+
} from "@typescript-eslint/utils";
|
|
12207
|
+
import ts3 from "typescript";
|
|
12208
|
+
var PREFER_NULLISH_FILTER_PREDICATE_DOCUMENTATION = {
|
|
12209
|
+
summary: "Prefer an explicit nullish predicate when `filter(Boolean)` removes only nullish values but does not narrow the result type.",
|
|
12210
|
+
rationale: "An explicit nullish predicate preserves the same runtime elements while letting TypeScript remove `null` and `undefined` from the result.",
|
|
12211
|
+
remediation: "Replace `filter(Boolean)` with `filter((value) => value !== null && value !== undefined)`.",
|
|
12212
|
+
category: "correctness",
|
|
12213
|
+
autofix: "suggestion",
|
|
12214
|
+
limitations: [
|
|
12215
|
+
"The receiver must resolve to the built-in Array or ReadonlyArray filter method.",
|
|
12216
|
+
"Broad primitive types, falsy literals, any, unknown, generics, intersections, custom filters, and shadowed Boolean bindings are excluded."
|
|
12217
|
+
],
|
|
12218
|
+
examples: [
|
|
12219
|
+
{
|
|
12220
|
+
id: "explicit-nullish-predicate",
|
|
12221
|
+
title: "Nullish filtering narrows the result",
|
|
12222
|
+
outcome: "no-match",
|
|
12223
|
+
files: [
|
|
12224
|
+
{
|
|
12225
|
+
path: "src/users.ts",
|
|
12226
|
+
source: "declare const users: readonly ({ id: string } | null)[];\nconst present = users.filter((user) => user !== null && user !== undefined);"
|
|
12227
|
+
}
|
|
12228
|
+
],
|
|
12229
|
+
focusPath: "src/users.ts",
|
|
12230
|
+
expectedCount: 0,
|
|
12231
|
+
public: true
|
|
12232
|
+
},
|
|
12233
|
+
{
|
|
12234
|
+
id: "boolean-nullish-filter",
|
|
12235
|
+
title: "Boolean filtering loses nullish narrowing",
|
|
12236
|
+
outcome: "match",
|
|
12237
|
+
files: [
|
|
12238
|
+
{
|
|
12239
|
+
path: "src/users.ts",
|
|
12240
|
+
source: "declare const users: readonly ({ id: string } | null)[];\nconst present = users.filter(Boolean);"
|
|
12241
|
+
}
|
|
12242
|
+
],
|
|
12243
|
+
focusPath: "src/users.ts",
|
|
12244
|
+
expectedCount: 1,
|
|
12245
|
+
public: true
|
|
12246
|
+
}
|
|
12247
|
+
]
|
|
12248
|
+
};
|
|
12249
|
+
function isUnshadowedBoolean(node, context) {
|
|
12250
|
+
const variable = ASTUtils16.findVariable(context.sourceCode.getScope(node), node.name);
|
|
12251
|
+
return variable === null || variable.defs.length === 0;
|
|
12252
|
+
}
|
|
12253
|
+
function isBuiltinArrayFilter(node, services) {
|
|
12254
|
+
const checker = services.program.getTypeChecker();
|
|
12255
|
+
const property = services.esTreeNodeToTSNodeMap.get(node.property);
|
|
12256
|
+
const symbol = checker.getSymbolAtLocation(property);
|
|
12257
|
+
return symbol?.declarations?.some((declaration) => {
|
|
12258
|
+
const owner = declaration.parent;
|
|
12259
|
+
return ts3.isInterfaceDeclaration(owner) && (owner.name.text === "Array" || owner.name.text === "ReadonlyArray") && services.program.isSourceFileDefaultLibrary(owner.getSourceFile());
|
|
12260
|
+
}) ?? false;
|
|
12261
|
+
}
|
|
12262
|
+
function arrayElementType(node, services) {
|
|
12263
|
+
const checker = services.program.getTypeChecker();
|
|
12264
|
+
const receiver = services.esTreeNodeToTSNodeMap.get(node);
|
|
12265
|
+
return checker.getIndexTypeOfType(checker.getTypeAtLocation(receiver), ts3.IndexKind.Number) ?? null;
|
|
12266
|
+
}
|
|
12267
|
+
var NULLISH_FLAGS = ts3.TypeFlags.Null | ts3.TypeFlags.Undefined;
|
|
12268
|
+
var UNKNOWN_FLAGS = ts3.TypeFlags.Any | ts3.TypeFlags.Unknown | ts3.TypeFlags.TypeParameter | ts3.TypeFlags.Intersection | ts3.TypeFlags.Enum | ts3.TypeFlags.EnumLiteral;
|
|
12269
|
+
function isNullishPlusTruthy(type, checker) {
|
|
12270
|
+
const members = type.isUnion() ? type.types : [type];
|
|
12271
|
+
let sawNullish = false;
|
|
12272
|
+
for (const member of members) {
|
|
12273
|
+
if ((member.flags & NULLISH_FLAGS) !== 0) {
|
|
12274
|
+
sawNullish = true;
|
|
12275
|
+
} else if ((member.flags & ts3.TypeFlags.Never) === 0 && !isProvablyTruthy(member, checker)) {
|
|
12276
|
+
return false;
|
|
12277
|
+
}
|
|
12278
|
+
}
|
|
12279
|
+
return sawNullish;
|
|
12280
|
+
}
|
|
12281
|
+
function isProvablyTruthy(type, checker) {
|
|
12282
|
+
if ((type.flags & UNKNOWN_FLAGS) !== 0) return false;
|
|
12283
|
+
if ((type.flags & ts3.TypeFlags.Object) !== 0) {
|
|
12284
|
+
return ![
|
|
12285
|
+
checker.getStringType(),
|
|
12286
|
+
checker.getNumberType(),
|
|
12287
|
+
checker.getBigIntType(),
|
|
12288
|
+
checker.getBooleanType()
|
|
12289
|
+
].some((primitive) => checker.isTypeAssignableTo(primitive, type));
|
|
12290
|
+
}
|
|
12291
|
+
if ((type.flags & (ts3.TypeFlags.ESSymbol | ts3.TypeFlags.UniqueESSymbol)) !== 0) return true;
|
|
12292
|
+
if ((type.flags & ts3.TypeFlags.BooleanLiteral) !== 0) {
|
|
12293
|
+
return type.intrinsicName === "true";
|
|
12294
|
+
}
|
|
12295
|
+
if ((type.flags & ts3.TypeFlags.StringLiteral) !== 0) {
|
|
12296
|
+
return type.value.length > 0;
|
|
12297
|
+
}
|
|
12298
|
+
if ((type.flags & ts3.TypeFlags.NumberLiteral) !== 0) {
|
|
12299
|
+
const value = type.value;
|
|
12300
|
+
return value !== 0 && !Number.isNaN(value);
|
|
12301
|
+
}
|
|
12302
|
+
if ((type.flags & ts3.TypeFlags.BigIntLiteral) !== 0) {
|
|
12303
|
+
return type.value.base10Value !== "0";
|
|
12304
|
+
}
|
|
12305
|
+
return false;
|
|
12306
|
+
}
|
|
12307
|
+
function availableParameterName(node, context) {
|
|
12308
|
+
for (const name of ["value", "item", "element", "candidate"]) {
|
|
12309
|
+
if (ASTUtils16.findVariable(context.sourceCode.getScope(node), name) === null) return name;
|
|
12310
|
+
}
|
|
12311
|
+
return null;
|
|
12312
|
+
}
|
|
12313
|
+
var prefer_nullish_filter_predicate_default = createRule({
|
|
12314
|
+
name: "prefer-nullish-filter-predicate",
|
|
12315
|
+
documentation: PREFER_NULLISH_FILTER_PREDICATE_DOCUMENTATION,
|
|
12316
|
+
meta: {
|
|
12317
|
+
type: "suggestion",
|
|
12318
|
+
docs: { description: PREFER_NULLISH_FILTER_PREDICATE_DOCUMENTATION.summary },
|
|
12319
|
+
hasSuggestions: true,
|
|
12320
|
+
schema: [],
|
|
12321
|
+
messages: {
|
|
12322
|
+
preferNullishPredicate: "This built-in array contains only nullish or provably truthy values, so `filter(Boolean)` preserves runtime values but loses nullish narrowing. Use an explicit nullish predicate.",
|
|
12323
|
+
replaceBoolean: "Replace `Boolean` with an explicit nullish predicate."
|
|
12324
|
+
}
|
|
12325
|
+
},
|
|
12326
|
+
defaultOptions: [],
|
|
12327
|
+
create(context) {
|
|
12328
|
+
if (isGeneratedFile(context.filename, context.sourceCode.text)) return {};
|
|
12329
|
+
let services;
|
|
12330
|
+
try {
|
|
12331
|
+
services = ESLintUtils5.getParserServices(context);
|
|
12332
|
+
} catch {
|
|
12333
|
+
services = null;
|
|
12334
|
+
}
|
|
12335
|
+
if (services === null) return {};
|
|
12336
|
+
return {
|
|
12337
|
+
CallExpression(node) {
|
|
12338
|
+
const callee = node.callee;
|
|
12339
|
+
const callback = node.arguments[0];
|
|
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;
|
|
12341
|
+
const elementType = arrayElementType(callee.object, services);
|
|
12342
|
+
const checker = services.program.getTypeChecker();
|
|
12343
|
+
if (elementType === null || !isNullishPlusTruthy(elementType, checker)) return;
|
|
12344
|
+
const parameter = availableParameterName(node, context);
|
|
12345
|
+
context.report({
|
|
12346
|
+
node: callback,
|
|
12347
|
+
messageId: "preferNullishPredicate",
|
|
12348
|
+
suggest: parameter === null ? null : [{
|
|
12349
|
+
messageId: "replaceBoolean",
|
|
12350
|
+
fix: (fixer) => fixer.replaceText(
|
|
12351
|
+
callback,
|
|
12352
|
+
`(${parameter}) => ${parameter} !== null && ${parameter} !== undefined`
|
|
12353
|
+
)
|
|
12354
|
+
}]
|
|
12355
|
+
});
|
|
12356
|
+
}
|
|
12357
|
+
};
|
|
12358
|
+
}
|
|
12359
|
+
});
|
|
12360
|
+
|
|
12361
|
+
// src/rules/prefer-await-in-async-return.ts
|
|
12362
|
+
import {
|
|
12363
|
+
ASTUtils as ASTUtils17,
|
|
12364
|
+
ESLintUtils as ESLintUtils6,
|
|
12365
|
+
AST_NODE_TYPES as AST_NODE_TYPES56
|
|
12016
12366
|
} from "@typescript-eslint/utils";
|
|
12017
|
-
import * as
|
|
12367
|
+
import * as ts4 from "typescript";
|
|
12018
12368
|
var PREFER_AWAIT_IN_ASYNC_RETURN_DOCUMENTATION = {
|
|
12019
12369
|
summary: "Prefer explicit `await` when an async function directly returns one typed Promise `.then` transform.",
|
|
12020
12370
|
rationale: "Mixing a directly returned Promise callback into otherwise async control flow makes sequencing and failures harder to read.",
|
|
@@ -12055,10 +12405,10 @@ var PREFER_AWAIT_IN_ASYNC_RETURN_DOCUMENTATION = {
|
|
|
12055
12405
|
};
|
|
12056
12406
|
function directAsyncReturnOwner(node) {
|
|
12057
12407
|
const parent = node.parent;
|
|
12058
|
-
if (parent.type ===
|
|
12408
|
+
if (parent.type === AST_NODE_TYPES56.ArrowFunctionExpression && parent.body === node) {
|
|
12059
12409
|
return parent.async && !parent.generator ? parent : null;
|
|
12060
12410
|
}
|
|
12061
|
-
if (parent.type !==
|
|
12411
|
+
if (parent.type !== AST_NODE_TYPES56.ReturnStatement || parent.argument !== node) {
|
|
12062
12412
|
return null;
|
|
12063
12413
|
}
|
|
12064
12414
|
let owner = parent.parent;
|
|
@@ -12068,15 +12418,15 @@ function directAsyncReturnOwner(node) {
|
|
|
12068
12418
|
return owner !== void 0 && owner.async && !owner.generator ? owner : null;
|
|
12069
12419
|
}
|
|
12070
12420
|
function isRuntimeFunction(node) {
|
|
12071
|
-
return node.type ===
|
|
12421
|
+
return node.type === AST_NODE_TYPES56.ArrowFunctionExpression || node.type === AST_NODE_TYPES56.FunctionDeclaration || node.type === AST_NODE_TYPES56.FunctionExpression;
|
|
12072
12422
|
}
|
|
12073
12423
|
function promiseThenReceiver(node) {
|
|
12074
12424
|
const callee = node.callee;
|
|
12075
|
-
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) {
|
|
12076
12426
|
return null;
|
|
12077
12427
|
}
|
|
12078
12428
|
const callback = node.arguments[0];
|
|
12079
|
-
if (callback === void 0 || callback.type !==
|
|
12429
|
+
if (callback === void 0 || callback.type !== AST_NODE_TYPES56.ArrowFunctionExpression && callback.type !== AST_NODE_TYPES56.FunctionExpression) {
|
|
12080
12430
|
return null;
|
|
12081
12431
|
}
|
|
12082
12432
|
return callee.object;
|
|
@@ -12085,14 +12435,14 @@ function isProvenPromiseLike(node, services) {
|
|
|
12085
12435
|
const checker = services.program.getTypeChecker();
|
|
12086
12436
|
const tsNode = services.esTreeNodeToTSNodeMap.get(node);
|
|
12087
12437
|
const receiverType = checker.getTypeAtLocation(tsNode);
|
|
12088
|
-
if ((receiverType.flags & (
|
|
12438
|
+
if ((receiverType.flags & (ts4.TypeFlags.Any | ts4.TypeFlags.Unknown | ts4.TypeFlags.Never)) !== 0) {
|
|
12089
12439
|
return false;
|
|
12090
12440
|
}
|
|
12091
12441
|
const thenSymbol = checker.getPropertyOfType(receiverType, "then");
|
|
12092
12442
|
const hasBuiltInPromiseDeclaration = thenSymbol?.declarations?.some(
|
|
12093
12443
|
(declaration) => {
|
|
12094
12444
|
let owner = declaration.parent;
|
|
12095
|
-
while (owner !== void 0 && !
|
|
12445
|
+
while (owner !== void 0 && !ts4.isInterfaceDeclaration(owner)) {
|
|
12096
12446
|
owner = owner.parent;
|
|
12097
12447
|
}
|
|
12098
12448
|
return owner !== void 0 && (owner.name.text === "Promise" || owner.name.text === "PromiseLike") && services.program.isSourceFileDefaultLibrary(owner.getSourceFile());
|
|
@@ -12117,32 +12467,32 @@ var prefer_await_in_async_return_default = createRule({
|
|
|
12117
12467
|
create(context) {
|
|
12118
12468
|
let services;
|
|
12119
12469
|
try {
|
|
12120
|
-
services =
|
|
12470
|
+
services = ESLintUtils6.getParserServices(context);
|
|
12121
12471
|
} catch {
|
|
12122
12472
|
services = null;
|
|
12123
12473
|
}
|
|
12124
12474
|
if (services === null) return {};
|
|
12125
12475
|
const frameworkLoaders = /* @__PURE__ */ new Set();
|
|
12126
12476
|
const rememberFrameworkLoader = (identifier) => {
|
|
12127
|
-
const variable =
|
|
12477
|
+
const variable = ASTUtils17.findVariable(context.sourceCode.getScope(identifier), identifier.name);
|
|
12128
12478
|
if (variable !== null) frameworkLoaders.add(variable);
|
|
12129
12479
|
};
|
|
12130
12480
|
const isFrameworkLoaderCallback = (owner) => {
|
|
12131
12481
|
const parent = owner.parent;
|
|
12132
|
-
if (parent.type !==
|
|
12133
|
-
const variable =
|
|
12482
|
+
if (parent.type !== AST_NODE_TYPES56.CallExpression || parent.arguments[0] !== owner || parent.callee.type !== AST_NODE_TYPES56.Identifier) return false;
|
|
12483
|
+
const variable = ASTUtils17.findVariable(context.sourceCode.getScope(parent.callee), parent.callee.name);
|
|
12134
12484
|
return variable !== null && frameworkLoaders.has(variable);
|
|
12135
12485
|
};
|
|
12136
12486
|
return {
|
|
12137
12487
|
ImportDeclaration(node) {
|
|
12138
12488
|
if (node.source.value === "react") {
|
|
12139
12489
|
for (const specifier of node.specifiers) {
|
|
12140
|
-
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);
|
|
12141
12491
|
}
|
|
12142
12492
|
}
|
|
12143
12493
|
if (node.source.value === "next/dynamic") {
|
|
12144
12494
|
for (const specifier of node.specifiers) {
|
|
12145
|
-
if (specifier.type ===
|
|
12495
|
+
if (specifier.type === AST_NODE_TYPES56.ImportDefaultSpecifier) rememberFrameworkLoader(specifier.local);
|
|
12146
12496
|
}
|
|
12147
12497
|
}
|
|
12148
12498
|
},
|
|
@@ -12160,7 +12510,7 @@ var prefer_await_in_async_return_default = createRule({
|
|
|
12160
12510
|
});
|
|
12161
12511
|
|
|
12162
12512
|
// src/rules/prefer-schema-for-api-payload.ts
|
|
12163
|
-
import { AST_NODE_TYPES as
|
|
12513
|
+
import { AST_NODE_TYPES as AST_NODE_TYPES57 } from "@typescript-eslint/utils";
|
|
12164
12514
|
var PREFER_SCHEMA_FOR_API_PAYLOAD_DOCUMENTATION = {
|
|
12165
12515
|
summary: "Require Zod (or similar) schema validation on `response.json()` / `JSON.parse()` results before property access.",
|
|
12166
12516
|
rationale: "External JSON is untrusted at runtime even when its expected TypeScript shape is known statically.",
|
|
@@ -12172,12 +12522,12 @@ var PREFER_SCHEMA_FOR_API_PAYLOAD_DOCUMENTATION = {
|
|
|
12172
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 }
|
|
12173
12523
|
]
|
|
12174
12524
|
};
|
|
12175
|
-
var
|
|
12525
|
+
var unwrap5 = (node) => {
|
|
12176
12526
|
let current = node;
|
|
12177
12527
|
while (current !== null && current !== void 0) {
|
|
12178
|
-
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) {
|
|
12179
12529
|
current = current.expression;
|
|
12180
|
-
} else if (current.type ===
|
|
12530
|
+
} else if (current.type === AST_NODE_TYPES57.ChainExpression) {
|
|
12181
12531
|
current = current.expression;
|
|
12182
12532
|
} else {
|
|
12183
12533
|
break;
|
|
@@ -12191,24 +12541,24 @@ var PROMISE_CHAIN_METHODS = /* @__PURE__ */ new Set([
|
|
|
12191
12541
|
"finally"
|
|
12192
12542
|
]);
|
|
12193
12543
|
var isSchemaParseReference = (node) => {
|
|
12194
|
-
const inner =
|
|
12195
|
-
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");
|
|
12196
12546
|
};
|
|
12197
12547
|
var isRawPayloadSource = (node, isKnownLocalText) => {
|
|
12198
|
-
let current =
|
|
12548
|
+
let current = unwrap5(node);
|
|
12199
12549
|
if (current === null) return false;
|
|
12200
|
-
if (current.type ===
|
|
12201
|
-
current =
|
|
12550
|
+
if (current.type === AST_NODE_TYPES57.AwaitExpression) {
|
|
12551
|
+
current = unwrap5(current.argument);
|
|
12202
12552
|
}
|
|
12203
|
-
if (current === null || current.type !==
|
|
12553
|
+
if (current === null || current.type !== AST_NODE_TYPES57.CallExpression) {
|
|
12204
12554
|
return false;
|
|
12205
12555
|
}
|
|
12206
|
-
const callee =
|
|
12207
|
-
if (callee === null || callee.type !==
|
|
12556
|
+
const callee = unwrap5(current.callee);
|
|
12557
|
+
if (callee === null || callee.type !== AST_NODE_TYPES57.MemberExpression) {
|
|
12208
12558
|
return false;
|
|
12209
12559
|
}
|
|
12210
|
-
const property =
|
|
12211
|
-
if (property === null || property.type !==
|
|
12560
|
+
const property = unwrap5(callee.property);
|
|
12561
|
+
if (property === null || property.type !== AST_NODE_TYPES57.Identifier) {
|
|
12212
12562
|
return false;
|
|
12213
12563
|
}
|
|
12214
12564
|
if (property.name === "json") {
|
|
@@ -12217,18 +12567,18 @@ var isRawPayloadSource = (node, isKnownLocalText) => {
|
|
|
12217
12567
|
if (PROMISE_CHAIN_METHODS.has(property.name)) {
|
|
12218
12568
|
return !current.arguments.some(isSchemaParseReference) && isRawPayloadSource(callee.object);
|
|
12219
12569
|
}
|
|
12220
|
-
const object =
|
|
12221
|
-
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;
|
|
12222
12572
|
};
|
|
12223
12573
|
var FILE_READ_RE = /^(readFile|readFileSync|readJson|readJsonSync|readJSON)$/;
|
|
12224
12574
|
var isDirectLocalFileRead = (node) => {
|
|
12225
|
-
let current =
|
|
12226
|
-
if (current?.type ===
|
|
12227
|
-
current =
|
|
12575
|
+
let current = unwrap5(node);
|
|
12576
|
+
if (current?.type === AST_NODE_TYPES57.AwaitExpression) {
|
|
12577
|
+
current = unwrap5(current.argument);
|
|
12228
12578
|
}
|
|
12229
|
-
if (current?.type !==
|
|
12230
|
-
const callee =
|
|
12231
|
-
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;
|
|
12232
12582
|
return name !== null && FILE_READ_RE.test(name);
|
|
12233
12583
|
};
|
|
12234
12584
|
var isLocalFileRead = (node) => {
|
|
@@ -12255,15 +12605,15 @@ var isLocalFileRead = (node) => {
|
|
|
12255
12605
|
var ASSERTION_CALLEE_RE = /^(expect|assert|should|invariant)$/;
|
|
12256
12606
|
var isInsideAssertion = (node) => {
|
|
12257
12607
|
for (let current = node.parent; current !== void 0 && current !== null; current = current.parent) {
|
|
12258
|
-
if (current.type !==
|
|
12608
|
+
if (current.type !== AST_NODE_TYPES57.CallExpression) continue;
|
|
12259
12609
|
let callee = current.callee;
|
|
12260
|
-
while (callee.type ===
|
|
12610
|
+
while (callee.type === AST_NODE_TYPES57.MemberExpression) {
|
|
12261
12611
|
callee = callee.object;
|
|
12262
12612
|
}
|
|
12263
|
-
if (callee.type ===
|
|
12613
|
+
if (callee.type === AST_NODE_TYPES57.CallExpression) {
|
|
12264
12614
|
callee = callee.callee;
|
|
12265
12615
|
}
|
|
12266
|
-
if (callee.type ===
|
|
12616
|
+
if (callee.type === AST_NODE_TYPES57.Identifier && ASSERTION_CALLEE_RE.test(callee.name)) {
|
|
12267
12617
|
return true;
|
|
12268
12618
|
}
|
|
12269
12619
|
}
|
|
@@ -12282,22 +12632,22 @@ var GUARD_NAME_RE = /^(?:is|validate|parse|assert|decode|coerce)[A-Z]/;
|
|
|
12282
12632
|
var isValidationRead = (node) => {
|
|
12283
12633
|
let current = node;
|
|
12284
12634
|
let parent = current.parent;
|
|
12285
|
-
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)) {
|
|
12286
12636
|
current = parent;
|
|
12287
12637
|
parent = parent.parent;
|
|
12288
12638
|
}
|
|
12289
12639
|
if (parent === null || parent === void 0) return false;
|
|
12290
|
-
if (parent.type ===
|
|
12640
|
+
if (parent.type === AST_NODE_TYPES57.UnaryExpression && parent.operator === "typeof" && parent.argument === current) {
|
|
12291
12641
|
return true;
|
|
12292
12642
|
}
|
|
12293
|
-
if (parent.type !==
|
|
12643
|
+
if (parent.type !== AST_NODE_TYPES57.CallExpression || !parent.arguments.some((arg) => arg === current)) {
|
|
12294
12644
|
return false;
|
|
12295
12645
|
}
|
|
12296
12646
|
const callee = parent.callee;
|
|
12297
|
-
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") {
|
|
12298
12648
|
return parent.arguments.length === 1;
|
|
12299
12649
|
}
|
|
12300
|
-
return callee.type ===
|
|
12650
|
+
return callee.type === AST_NODE_TYPES57.Identifier && GUARD_NAME_RE.test(callee.name);
|
|
12301
12651
|
};
|
|
12302
12652
|
var PRIMITIVE_TYPEOF_RESULTS = /* @__PURE__ */ new Set([
|
|
12303
12653
|
"bigint",
|
|
@@ -12308,13 +12658,13 @@ var PRIMITIVE_TYPEOF_RESULTS = /* @__PURE__ */ new Set([
|
|
|
12308
12658
|
"undefined"
|
|
12309
12659
|
]);
|
|
12310
12660
|
var bindingValidationPolarity = (test, bindingName) => {
|
|
12311
|
-
if (test.type ===
|
|
12661
|
+
if (test.type === AST_NODE_TYPES57.UnaryExpression && test.operator === "!") {
|
|
12312
12662
|
const inner = bindingValidationPolarity(test.argument, bindingName);
|
|
12313
12663
|
return inner === "valid-when-true" ? "valid-when-false" : inner === "valid-when-false" ? "valid-when-true" : null;
|
|
12314
12664
|
}
|
|
12315
|
-
if (test.type ===
|
|
12316
|
-
const typeofName = (node) => node.type ===
|
|
12317
|
-
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;
|
|
12318
12668
|
const matches = typeofName(test.left) === bindingName && literalType(test.right) !== null || typeofName(test.right) === bindingName && literalType(test.left) !== null;
|
|
12319
12669
|
if (!matches) return null;
|
|
12320
12670
|
if (test.operator === "===" || test.operator === "==") {
|
|
@@ -12322,9 +12672,9 @@ var bindingValidationPolarity = (test, bindingName) => {
|
|
|
12322
12672
|
}
|
|
12323
12673
|
return test.operator === "!==" || test.operator === "!=" ? "valid-when-false" : null;
|
|
12324
12674
|
}
|
|
12325
|
-
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;
|
|
12326
12676
|
};
|
|
12327
|
-
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;
|
|
12328
12678
|
var isSamePlainMember = (node, access) => {
|
|
12329
12679
|
const candidate2 = plainMemberAccess(node);
|
|
12330
12680
|
return candidate2 !== null && candidate2.object === access.object && candidate2.property === access.property;
|
|
@@ -12332,19 +12682,19 @@ var isSamePlainMember = (node, access) => {
|
|
|
12332
12682
|
var nodeWithin2 = (node, container) => node.range[0] >= container.range[0] && node.range[1] <= container.range[1];
|
|
12333
12683
|
var isUseWithinValidatedBranch = (node, bindingName) => {
|
|
12334
12684
|
for (let current = node.parent; current !== void 0 && current !== null; current = current.parent) {
|
|
12335
|
-
if (current.type ===
|
|
12685
|
+
if (current.type === AST_NODE_TYPES57.ConditionalExpression) {
|
|
12336
12686
|
const polarity = bindingValidationPolarity(current.test, bindingName);
|
|
12337
12687
|
if (polarity === "valid-when-true" && nodeWithin2(node, current.consequent) || polarity === "valid-when-false" && nodeWithin2(node, current.alternate)) {
|
|
12338
12688
|
return true;
|
|
12339
12689
|
}
|
|
12340
12690
|
}
|
|
12341
|
-
if (current.type ===
|
|
12691
|
+
if (current.type === AST_NODE_TYPES57.IfStatement) {
|
|
12342
12692
|
const polarity = bindingValidationPolarity(current.test, bindingName);
|
|
12343
12693
|
if (polarity === "valid-when-true" && nodeWithin2(node, current.consequent) || polarity === "valid-when-false" && current.alternate !== null && nodeWithin2(node, current.alternate)) {
|
|
12344
12694
|
return true;
|
|
12345
12695
|
}
|
|
12346
12696
|
}
|
|
12347
|
-
if (current.type ===
|
|
12697
|
+
if (current.type === AST_NODE_TYPES57.FunctionDeclaration || current.type === AST_NODE_TYPES57.FunctionExpression || current.type === AST_NODE_TYPES57.ArrowFunctionExpression) {
|
|
12348
12698
|
return false;
|
|
12349
12699
|
}
|
|
12350
12700
|
}
|
|
@@ -12352,32 +12702,32 @@ var isUseWithinValidatedBranch = (node, bindingName) => {
|
|
|
12352
12702
|
};
|
|
12353
12703
|
var isMemberUseWithinValidatedBranch = (node, access) => {
|
|
12354
12704
|
for (let current = node.parent; current !== void 0 && current !== null; current = current.parent) {
|
|
12355
|
-
if (current.type ===
|
|
12705
|
+
if (current.type === AST_NODE_TYPES57.ConditionalExpression) {
|
|
12356
12706
|
const polarity = memberValidationPolarity(current.test, access);
|
|
12357
12707
|
if (polarity === "valid-when-true" && nodeWithin2(node, current.consequent) || polarity === "valid-when-false" && nodeWithin2(node, current.alternate)) {
|
|
12358
12708
|
return true;
|
|
12359
12709
|
}
|
|
12360
12710
|
}
|
|
12361
|
-
if (current.type ===
|
|
12711
|
+
if (current.type === AST_NODE_TYPES57.IfStatement) {
|
|
12362
12712
|
const polarity = memberValidationPolarity(current.test, access);
|
|
12363
12713
|
if (polarity === "valid-when-true" && nodeWithin2(node, current.consequent) || polarity === "valid-when-false" && current.alternate !== null && nodeWithin2(node, current.alternate)) {
|
|
12364
12714
|
return true;
|
|
12365
12715
|
}
|
|
12366
12716
|
}
|
|
12367
|
-
if (current.type ===
|
|
12717
|
+
if (current.type === AST_NODE_TYPES57.FunctionDeclaration || current.type === AST_NODE_TYPES57.FunctionExpression || current.type === AST_NODE_TYPES57.ArrowFunctionExpression) {
|
|
12368
12718
|
return false;
|
|
12369
12719
|
}
|
|
12370
12720
|
}
|
|
12371
12721
|
return false;
|
|
12372
12722
|
};
|
|
12373
12723
|
var memberValidationPolarity = (test, access) => {
|
|
12374
|
-
if (test.type ===
|
|
12724
|
+
if (test.type === AST_NODE_TYPES57.UnaryExpression && test.operator === "!") {
|
|
12375
12725
|
const inner = memberValidationPolarity(test.argument, access);
|
|
12376
12726
|
return inner === "valid-when-true" ? "valid-when-false" : inner === "valid-when-false" ? "valid-when-true" : null;
|
|
12377
12727
|
}
|
|
12378
|
-
if (test.type ===
|
|
12379
|
-
const isMatchingTypeof = (node) => node.type ===
|
|
12380
|
-
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);
|
|
12381
12731
|
if (!(isMatchingTypeof(test.left) && isPrimitiveType(test.right) || isMatchingTypeof(test.right) && isPrimitiveType(test.left))) {
|
|
12382
12732
|
return null;
|
|
12383
12733
|
}
|
|
@@ -12386,15 +12736,15 @@ var memberValidationPolarity = (test, access) => {
|
|
|
12386
12736
|
}
|
|
12387
12737
|
return test.operator === "!==" || test.operator === "!=" ? "valid-when-false" : null;
|
|
12388
12738
|
}
|
|
12389
|
-
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;
|
|
12390
12740
|
};
|
|
12391
12741
|
var isFullyValidatedExtractedBinding = (member, source, context) => {
|
|
12392
12742
|
const isValidationReference = (identifier) => {
|
|
12393
12743
|
for (let current = identifier.parent; current !== void 0 && current !== null; current = current.parent) {
|
|
12394
|
-
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) {
|
|
12395
12745
|
return true;
|
|
12396
12746
|
}
|
|
12397
|
-
if (current.type !==
|
|
12747
|
+
if (current.type !== AST_NODE_TYPES57.UnaryExpression && current.type !== AST_NODE_TYPES57.MemberExpression && current.type !== AST_NODE_TYPES57.CallExpression) {
|
|
12398
12748
|
return false;
|
|
12399
12749
|
}
|
|
12400
12750
|
}
|
|
@@ -12402,7 +12752,7 @@ var isFullyValidatedExtractedBinding = (member, source, context) => {
|
|
|
12402
12752
|
};
|
|
12403
12753
|
const isGuardedUse = (identifier) => {
|
|
12404
12754
|
for (let current = identifier.parent; current !== void 0 && current !== null; current = current.parent) {
|
|
12405
|
-
if (current.type ===
|
|
12755
|
+
if (current.type === AST_NODE_TYPES57.ConditionalExpression) {
|
|
12406
12756
|
const polarity = bindingValidationPolarity(current.test, identifier.name);
|
|
12407
12757
|
if (polarity === "valid-when-true" && nodeWithin2(identifier, current.consequent)) {
|
|
12408
12758
|
return true;
|
|
@@ -12411,7 +12761,7 @@ var isFullyValidatedExtractedBinding = (member, source, context) => {
|
|
|
12411
12761
|
return true;
|
|
12412
12762
|
}
|
|
12413
12763
|
}
|
|
12414
|
-
if (current.type ===
|
|
12764
|
+
if (current.type === AST_NODE_TYPES57.IfStatement) {
|
|
12415
12765
|
const polarity = bindingValidationPolarity(current.test, identifier.name);
|
|
12416
12766
|
if (polarity === "valid-when-true" && nodeWithin2(identifier, current.consequent)) {
|
|
12417
12767
|
return true;
|
|
@@ -12420,14 +12770,14 @@ var isFullyValidatedExtractedBinding = (member, source, context) => {
|
|
|
12420
12770
|
return true;
|
|
12421
12771
|
}
|
|
12422
12772
|
}
|
|
12423
|
-
if (current.type ===
|
|
12773
|
+
if (current.type === AST_NODE_TYPES57.FunctionDeclaration || current.type === AST_NODE_TYPES57.FunctionExpression || current.type === AST_NODE_TYPES57.ArrowFunctionExpression) {
|
|
12424
12774
|
return false;
|
|
12425
12775
|
}
|
|
12426
12776
|
}
|
|
12427
12777
|
return false;
|
|
12428
12778
|
};
|
|
12429
12779
|
const declarator = member.parent;
|
|
12430
|
-
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") {
|
|
12431
12781
|
return false;
|
|
12432
12782
|
}
|
|
12433
12783
|
const extracted = context.sourceCode.getDeclaredVariables(declarator)[0];
|
|
@@ -12435,7 +12785,7 @@ var isFullyValidatedExtractedBinding = (member, source, context) => {
|
|
|
12435
12785
|
let hasValueUse = false;
|
|
12436
12786
|
for (const reference of extracted.references) {
|
|
12437
12787
|
const identifier = reference.identifier;
|
|
12438
|
-
if (identifier.type !==
|
|
12788
|
+
if (identifier.type !== AST_NODE_TYPES57.Identifier) return false;
|
|
12439
12789
|
if (nodeWithin2(identifier, declarator)) continue;
|
|
12440
12790
|
if (isValidationReference(identifier)) continue;
|
|
12441
12791
|
hasValueUse = true;
|
|
@@ -12448,17 +12798,17 @@ var isGuardTestPosition = (node) => {
|
|
|
12448
12798
|
let parent = current.parent;
|
|
12449
12799
|
while (parent !== void 0 && parent !== null) {
|
|
12450
12800
|
switch (parent.type) {
|
|
12451
|
-
case
|
|
12452
|
-
case
|
|
12453
|
-
case
|
|
12801
|
+
case AST_NODE_TYPES57.UnaryExpression:
|
|
12802
|
+
case AST_NODE_TYPES57.LogicalExpression:
|
|
12803
|
+
case AST_NODE_TYPES57.ChainExpression:
|
|
12454
12804
|
current = parent;
|
|
12455
12805
|
parent = parent.parent;
|
|
12456
12806
|
continue;
|
|
12457
|
-
case
|
|
12458
|
-
case
|
|
12459
|
-
case
|
|
12460
|
-
case
|
|
12461
|
-
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:
|
|
12462
12812
|
return parent.test === current;
|
|
12463
12813
|
default:
|
|
12464
12814
|
return false;
|
|
@@ -12467,8 +12817,8 @@ var isGuardTestPosition = (node) => {
|
|
|
12467
12817
|
return false;
|
|
12468
12818
|
};
|
|
12469
12819
|
var unvalidatedVariableRef = (node, scope, tracked) => {
|
|
12470
|
-
const unwrapped =
|
|
12471
|
-
if (unwrapped === null || unwrapped.type !==
|
|
12820
|
+
const unwrapped = unwrap5(node);
|
|
12821
|
+
if (unwrapped === null || unwrapped.type !== AST_NODE_TYPES57.Identifier) {
|
|
12472
12822
|
return null;
|
|
12473
12823
|
}
|
|
12474
12824
|
const variable = findVariable2(scope, unwrapped.name);
|
|
@@ -12496,8 +12846,8 @@ var prefer_schema_for_api_payload_default = createRule({
|
|
|
12496
12846
|
const aliasGroups = /* @__PURE__ */ new Map();
|
|
12497
12847
|
const localFileTextVariables = /* @__PURE__ */ new Set();
|
|
12498
12848
|
const localFileTextRef = (node, scope) => {
|
|
12499
|
-
const unwrapped =
|
|
12500
|
-
if (unwrapped?.type !==
|
|
12849
|
+
const unwrapped = unwrap5(node);
|
|
12850
|
+
if (unwrapped?.type !== AST_NODE_TYPES57.Identifier) return null;
|
|
12501
12851
|
const variable = findVariable2(scope, unwrapped.name);
|
|
12502
12852
|
return variable !== null && localFileTextVariables.has(variable) ? variable : null;
|
|
12503
12853
|
};
|
|
@@ -12566,7 +12916,7 @@ var prefer_schema_for_api_payload_default = createRule({
|
|
|
12566
12916
|
return {
|
|
12567
12917
|
VariableDeclarator(node) {
|
|
12568
12918
|
const scope = context.sourceCode.getScope(node);
|
|
12569
|
-
if (node.id.type ===
|
|
12919
|
+
if (node.id.type === AST_NODE_TYPES57.Identifier) {
|
|
12570
12920
|
const variable = context.sourceCode.getDeclaredVariables(node)[0];
|
|
12571
12921
|
if (variable !== void 0) {
|
|
12572
12922
|
updateLocalFileText(variable, node.init, scope);
|
|
@@ -12574,7 +12924,7 @@ var prefer_schema_for_api_payload_default = createRule({
|
|
|
12574
12924
|
trackInitializer(node, scope);
|
|
12575
12925
|
return;
|
|
12576
12926
|
}
|
|
12577
|
-
if (node.id.type ===
|
|
12927
|
+
if (node.id.type === AST_NODE_TYPES57.ObjectPattern || node.id.type === AST_NODE_TYPES57.ArrayPattern) {
|
|
12578
12928
|
if (isRawPayloadSource(
|
|
12579
12929
|
node.init,
|
|
12580
12930
|
(candidate2) => localFileTextRef(candidate2, scope) !== null
|
|
@@ -12591,7 +12941,7 @@ var prefer_schema_for_api_payload_default = createRule({
|
|
|
12591
12941
|
},
|
|
12592
12942
|
AssignmentExpression(node) {
|
|
12593
12943
|
const scope = context.sourceCode.getScope(node);
|
|
12594
|
-
if (node.left.type ===
|
|
12944
|
+
if (node.left.type === AST_NODE_TYPES57.Identifier) {
|
|
12595
12945
|
const variable = findVariable2(scope, node.left.name);
|
|
12596
12946
|
if (variable === null) return;
|
|
12597
12947
|
const isLocalText = (candidate2) => localFileTextRef(candidate2, scope) !== null;
|
|
@@ -12605,7 +12955,7 @@ var prefer_schema_for_api_payload_default = createRule({
|
|
|
12605
12955
|
}
|
|
12606
12956
|
return;
|
|
12607
12957
|
}
|
|
12608
|
-
if (node.left.type ===
|
|
12958
|
+
if (node.left.type === AST_NODE_TYPES57.ObjectPattern || node.left.type === AST_NODE_TYPES57.ArrayPattern) {
|
|
12609
12959
|
if (isRawPayloadSource(
|
|
12610
12960
|
node.right,
|
|
12611
12961
|
(candidate2) => localFileTextRef(candidate2, scope) !== null
|
|
@@ -12625,15 +12975,15 @@ var prefer_schema_for_api_payload_default = createRule({
|
|
|
12625
12975
|
}
|
|
12626
12976
|
},
|
|
12627
12977
|
CallExpression(node) {
|
|
12628
|
-
if (node.callee.type !==
|
|
12978
|
+
if (node.callee.type !== AST_NODE_TYPES57.Identifier) return;
|
|
12629
12979
|
if (!GUARD_NAME_RE.test(node.callee.name) && !isGuardTestPosition(node)) {
|
|
12630
12980
|
return;
|
|
12631
12981
|
}
|
|
12632
12982
|
const scope = context.sourceCode.getScope(node);
|
|
12633
12983
|
for (const arg of node.arguments) {
|
|
12634
|
-
if (arg.type ===
|
|
12635
|
-
const unwrapped =
|
|
12636
|
-
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) {
|
|
12637
12987
|
continue;
|
|
12638
12988
|
}
|
|
12639
12989
|
const variable = findVariable2(scope, unwrapped.name);
|
|
@@ -12644,20 +12994,20 @@ var prefer_schema_for_api_payload_default = createRule({
|
|
|
12644
12994
|
if (isInsideAssertion(node)) return;
|
|
12645
12995
|
if (isValidationRead(node)) return;
|
|
12646
12996
|
const scope = context.sourceCode.getScope(node);
|
|
12647
|
-
const obj =
|
|
12997
|
+
const obj = unwrap5(node.object);
|
|
12648
12998
|
if (isRawPayloadSource(
|
|
12649
12999
|
obj,
|
|
12650
13000
|
(candidate2) => localFileTextRef(candidate2, scope) !== null
|
|
12651
13001
|
)) {
|
|
12652
13002
|
const parent = node.parent;
|
|
12653
|
-
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))) {
|
|
12654
13004
|
return;
|
|
12655
13005
|
}
|
|
12656
13006
|
context.report({ node, messageId: "unparsedJsonAccess" });
|
|
12657
13007
|
return;
|
|
12658
13008
|
}
|
|
12659
|
-
const variable = obj?.type ===
|
|
12660
|
-
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) {
|
|
12661
13011
|
if (isUseWithinValidatedBranch(node, obj.name)) {
|
|
12662
13012
|
return;
|
|
12663
13013
|
}
|
|
@@ -12676,8 +13026,122 @@ var prefer_schema_for_api_payload_default = createRule({
|
|
|
12676
13026
|
}
|
|
12677
13027
|
});
|
|
12678
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
|
+
|
|
12679
13143
|
// src/rules/prefer-semantic-colors.ts
|
|
12680
|
-
import { AST_NODE_TYPES as
|
|
13144
|
+
import { AST_NODE_TYPES as AST_NODE_TYPES60 } from "@typescript-eslint/utils";
|
|
12681
13145
|
import { existsSync, readdirSync, readFileSync } from "fs";
|
|
12682
13146
|
import { dirname, join, parse } from "path";
|
|
12683
13147
|
|
|
@@ -12789,7 +13253,7 @@ var SVG_EXEMPT_COLOR_VALUES = /* @__PURE__ */ new Set([
|
|
|
12789
13253
|
var isInsideSvg = (node) => {
|
|
12790
13254
|
let current = node.parent;
|
|
12791
13255
|
while (current !== void 0 && current !== null) {
|
|
12792
|
-
if (current.type ===
|
|
13256
|
+
if (current.type === AST_NODE_TYPES60.JSXElement) {
|
|
12793
13257
|
const name = jsxElementName(current);
|
|
12794
13258
|
if (name !== null && isSvgLikeElementName(name)) return true;
|
|
12795
13259
|
}
|
|
@@ -12799,8 +13263,8 @@ var isInsideSvg = (node) => {
|
|
|
12799
13263
|
};
|
|
12800
13264
|
function jsxElementName(node) {
|
|
12801
13265
|
const name = node.openingElement.name;
|
|
12802
|
-
if (name.type ===
|
|
12803
|
-
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) {
|
|
12804
13268
|
return name.property.name;
|
|
12805
13269
|
}
|
|
12806
13270
|
return null;
|
|
@@ -12826,7 +13290,7 @@ function isSvgLikeElementName(name) {
|
|
|
12826
13290
|
var isInsideIconFactoryPath = (node) => {
|
|
12827
13291
|
let current = node.parent;
|
|
12828
13292
|
while (current !== void 0 && current !== null) {
|
|
12829
|
-
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") {
|
|
12830
13294
|
return true;
|
|
12831
13295
|
}
|
|
12832
13296
|
current = current.parent;
|
|
@@ -12960,12 +13424,12 @@ var expandWorkspaceGlob = (root, glob) => {
|
|
|
12960
13424
|
return readdirSync(parent, { withFileTypes: true }).filter((entry) => entry.isDirectory() && !entry.name.startsWith(".")).map((entry) => join(parent, entry.name));
|
|
12961
13425
|
};
|
|
12962
13426
|
var propName = (key) => {
|
|
12963
|
-
if (key.type ===
|
|
12964
|
-
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;
|
|
12965
13429
|
return null;
|
|
12966
13430
|
};
|
|
12967
13431
|
var staticallyImportsEmailOrPdfRenderer = (program) => program.body.some((statement) => {
|
|
12968
|
-
if (statement.type !==
|
|
13432
|
+
if (statement.type !== AST_NODE_TYPES60.ImportDeclaration && statement.type !== AST_NODE_TYPES60.ExportNamedDeclaration && statement.type !== AST_NODE_TYPES60.ExportAllDeclaration) {
|
|
12969
13433
|
return false;
|
|
12970
13434
|
}
|
|
12971
13435
|
return statement.source !== null && typeof statement.source.value === "string" && EMAIL_OR_PDF_MODULE_RE.test(statement.source.value);
|
|
@@ -13002,43 +13466,43 @@ var prefer_semantic_colors_default = createRule({
|
|
|
13002
13466
|
}
|
|
13003
13467
|
let importsEmailOrPdfRenderer = false;
|
|
13004
13468
|
const pendingReports = [];
|
|
13005
|
-
const
|
|
13469
|
+
const report2 = (node, messageId, data) => {
|
|
13006
13470
|
pendingReports.push({ node, messageId, data });
|
|
13007
13471
|
};
|
|
13008
13472
|
const reportClasses = (value, node) => {
|
|
13009
13473
|
for (const token of classTokens(value)) {
|
|
13010
13474
|
const base = tailwindBase(token);
|
|
13011
13475
|
if (RAW_PALETTE_RE.test(base)) {
|
|
13012
|
-
|
|
13476
|
+
report2(node, "rawPalette", { class: token });
|
|
13013
13477
|
} else if (ARBITRARY_COLOR_RE.test(base) && !CSS_VAR_REFERENCE_RE.test(base)) {
|
|
13014
|
-
|
|
13478
|
+
report2(node, "arbitraryColor", { class: token });
|
|
13015
13479
|
}
|
|
13016
13480
|
}
|
|
13017
13481
|
};
|
|
13018
13482
|
const checkClassNode = (node) => {
|
|
13019
13483
|
if (node === null) return;
|
|
13020
13484
|
switch (node.type) {
|
|
13021
|
-
case
|
|
13485
|
+
case AST_NODE_TYPES60.Literal:
|
|
13022
13486
|
if (typeof node.value === "string") reportClasses(node.value, node);
|
|
13023
13487
|
break;
|
|
13024
|
-
case
|
|
13488
|
+
case AST_NODE_TYPES60.TemplateLiteral:
|
|
13025
13489
|
for (const quasi of node.quasis) reportClasses(quasi.value.cooked ?? "", quasi);
|
|
13026
13490
|
break;
|
|
13027
|
-
case
|
|
13491
|
+
case AST_NODE_TYPES60.ArrayExpression:
|
|
13028
13492
|
for (const element of node.elements) {
|
|
13029
|
-
if (element !== null && element.type !==
|
|
13493
|
+
if (element !== null && element.type !== AST_NODE_TYPES60.SpreadElement) checkClassNode(element);
|
|
13030
13494
|
}
|
|
13031
13495
|
break;
|
|
13032
|
-
case
|
|
13496
|
+
case AST_NODE_TYPES60.ObjectExpression:
|
|
13033
13497
|
for (const property of node.properties) {
|
|
13034
|
-
if (property.type ===
|
|
13498
|
+
if (property.type === AST_NODE_TYPES60.Property) checkClassNode(property.value);
|
|
13035
13499
|
}
|
|
13036
13500
|
break;
|
|
13037
|
-
case
|
|
13501
|
+
case AST_NODE_TYPES60.ConditionalExpression:
|
|
13038
13502
|
checkClassNode(node.consequent);
|
|
13039
13503
|
checkClassNode(node.alternate);
|
|
13040
13504
|
break;
|
|
13041
|
-
case
|
|
13505
|
+
case AST_NODE_TYPES60.LogicalExpression:
|
|
13042
13506
|
checkClassNode(node.right);
|
|
13043
13507
|
break;
|
|
13044
13508
|
default:
|
|
@@ -13046,32 +13510,32 @@ var prefer_semantic_colors_default = createRule({
|
|
|
13046
13510
|
}
|
|
13047
13511
|
};
|
|
13048
13512
|
const checkColorValueNode = (node) => {
|
|
13049
|
-
if (node.type ===
|
|
13050
|
-
|
|
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 });
|
|
13051
13515
|
}
|
|
13052
13516
|
};
|
|
13053
13517
|
return {
|
|
13054
13518
|
"JSXAttribute[name.name='className']"(node) {
|
|
13055
13519
|
if (node.value === null) return;
|
|
13056
|
-
if (node.value.type ===
|
|
13057
|
-
else if (node.value.type ===
|
|
13058
|
-
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) {
|
|
13059
13523
|
checkClassNode(node.value.expression);
|
|
13060
13524
|
}
|
|
13061
13525
|
}
|
|
13062
13526
|
},
|
|
13063
13527
|
CallExpression(node) {
|
|
13064
|
-
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)) {
|
|
13065
13529
|
importsEmailOrPdfRenderer = true;
|
|
13066
13530
|
}
|
|
13067
|
-
if (node.callee.type ===
|
|
13531
|
+
if (node.callee.type === AST_NODE_TYPES60.Identifier && CLASS_FNS.has(node.callee.name)) {
|
|
13068
13532
|
for (const arg of node.arguments) {
|
|
13069
|
-
if (arg.type !==
|
|
13533
|
+
if (arg.type !== AST_NODE_TYPES60.SpreadElement) checkClassNode(arg);
|
|
13070
13534
|
}
|
|
13071
13535
|
}
|
|
13072
13536
|
},
|
|
13073
13537
|
VariableDeclarator(node) {
|
|
13074
|
-
if (node.id.type ===
|
|
13538
|
+
if (node.id.type === AST_NODE_TYPES60.Identifier && CLASS_NAME_RE.test(node.id.name)) {
|
|
13075
13539
|
checkClassNode(node.init);
|
|
13076
13540
|
}
|
|
13077
13541
|
},
|
|
@@ -13081,9 +13545,9 @@ var prefer_semantic_colors_default = createRule({
|
|
|
13081
13545
|
},
|
|
13082
13546
|
// SVG artwork colors are exempt; component presentation colors still report.
|
|
13083
13547
|
"JSXAttribute[name.name=/^(fill|stroke|color)$/]"(node) {
|
|
13084
|
-
if (node.value?.type !==
|
|
13548
|
+
if (node.value?.type !== AST_NODE_TYPES60.Literal) return;
|
|
13085
13549
|
const owner = node.parent.name;
|
|
13086
|
-
if (owner.type ===
|
|
13550
|
+
if (owner.type === AST_NODE_TYPES60.JSXIdentifier && SVG_SHAPE_PRIMITIVES.has(owner.name)) {
|
|
13087
13551
|
return;
|
|
13088
13552
|
}
|
|
13089
13553
|
if (typeof node.value.value === "string" && SVG_EXEMPT_COLOR_VALUES.has(node.value.value.toLowerCase())) {
|
|
@@ -13097,7 +13561,7 @@ var prefer_semantic_colors_default = createRule({
|
|
|
13097
13561
|
if (name !== null && STYLE_COLOR_PROPS.has(name)) checkColorValueNode(node.value);
|
|
13098
13562
|
},
|
|
13099
13563
|
ImportExpression(node) {
|
|
13100
|
-
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)) {
|
|
13101
13565
|
importsEmailOrPdfRenderer = true;
|
|
13102
13566
|
}
|
|
13103
13567
|
},
|
|
@@ -13299,7 +13763,7 @@ var prefer_server_actions_default = createRule({
|
|
|
13299
13763
|
});
|
|
13300
13764
|
|
|
13301
13765
|
// src/rules/prefer-whole-object-assertion.ts
|
|
13302
|
-
import { AST_NODE_TYPES as
|
|
13766
|
+
import { AST_NODE_TYPES as AST_NODE_TYPES61 } from "@typescript-eslint/utils";
|
|
13303
13767
|
var MERGEABLE_MATCHERS = /* @__PURE__ */ new Set(["toBe", "toEqual", "toStrictEqual"]);
|
|
13304
13768
|
var SYNTHETIC_LITERAL_MATCHERS = /* @__PURE__ */ new Map([
|
|
13305
13769
|
["toBeNull", "null"],
|
|
@@ -13324,11 +13788,11 @@ var PREFER_WHOLE_OBJECT_ASSERTION_DOCUMENTATION = {
|
|
|
13324
13788
|
};
|
|
13325
13789
|
function literalText(node, getText) {
|
|
13326
13790
|
switch (node.type) {
|
|
13327
|
-
case
|
|
13791
|
+
case AST_NODE_TYPES61.Literal:
|
|
13328
13792
|
return "regex" in node ? null : getText(node);
|
|
13329
|
-
case
|
|
13793
|
+
case AST_NODE_TYPES61.TemplateLiteral:
|
|
13330
13794
|
return node.expressions.length === 0 ? getText(node) : null;
|
|
13331
|
-
case
|
|
13795
|
+
case AST_NODE_TYPES61.UnaryExpression:
|
|
13332
13796
|
return NUMERIC_SIGNS2.has(node.operator) && literalText(node.argument, getText) !== null ? getText(node) : null;
|
|
13333
13797
|
default:
|
|
13334
13798
|
return null;
|
|
@@ -13336,15 +13800,15 @@ function literalText(node, getText) {
|
|
|
13336
13800
|
}
|
|
13337
13801
|
function isPureReceiver(node) {
|
|
13338
13802
|
switch (node.type) {
|
|
13339
|
-
case
|
|
13340
|
-
case
|
|
13803
|
+
case AST_NODE_TYPES61.Identifier:
|
|
13804
|
+
case AST_NODE_TYPES61.ThisExpression:
|
|
13341
13805
|
return true;
|
|
13342
|
-
case
|
|
13806
|
+
case AST_NODE_TYPES61.MemberExpression:
|
|
13343
13807
|
if (node.optional) {
|
|
13344
13808
|
return false;
|
|
13345
13809
|
}
|
|
13346
13810
|
if (node.computed) {
|
|
13347
|
-
return node.property.type ===
|
|
13811
|
+
return node.property.type === AST_NODE_TYPES61.Literal && isPureReceiver(node.object);
|
|
13348
13812
|
}
|
|
13349
13813
|
return isPureReceiver(node.object);
|
|
13350
13814
|
default:
|
|
@@ -13352,7 +13816,7 @@ function isPureReceiver(node) {
|
|
|
13352
13816
|
}
|
|
13353
13817
|
}
|
|
13354
13818
|
function literalIndex(node) {
|
|
13355
|
-
if (node.type !==
|
|
13819
|
+
if (node.type !== AST_NODE_TYPES61.Literal || typeof node.value !== "number") {
|
|
13356
13820
|
return null;
|
|
13357
13821
|
}
|
|
13358
13822
|
return Number.isInteger(node.value) && node.value >= 0 ? node.value : null;
|
|
@@ -13360,8 +13824,8 @@ function literalIndex(node) {
|
|
|
13360
13824
|
function propertyAccess(node) {
|
|
13361
13825
|
const path = [];
|
|
13362
13826
|
let current = node;
|
|
13363
|
-
while (current.type ===
|
|
13364
|
-
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;
|
|
13365
13829
|
path.unshift(current.property.name);
|
|
13366
13830
|
current = current.object;
|
|
13367
13831
|
}
|
|
@@ -13389,24 +13853,24 @@ var prefer_whole_object_assertion_default = createRule({
|
|
|
13389
13853
|
}
|
|
13390
13854
|
const { sourceCode } = context;
|
|
13391
13855
|
function parseAssertion(statement) {
|
|
13392
|
-
if (statement.type !==
|
|
13856
|
+
if (statement.type !== AST_NODE_TYPES61.ExpressionStatement) {
|
|
13393
13857
|
return null;
|
|
13394
13858
|
}
|
|
13395
13859
|
const call = statement.expression;
|
|
13396
|
-
if (call.type !==
|
|
13860
|
+
if (call.type !== AST_NODE_TYPES61.CallExpression) {
|
|
13397
13861
|
return null;
|
|
13398
13862
|
}
|
|
13399
13863
|
const callee = call.callee;
|
|
13400
|
-
if (callee.type !==
|
|
13864
|
+
if (callee.type !== AST_NODE_TYPES61.MemberExpression || callee.computed || callee.property.type !== AST_NODE_TYPES61.Identifier) {
|
|
13401
13865
|
return null;
|
|
13402
13866
|
}
|
|
13403
13867
|
const matcher = callee.property.name;
|
|
13404
13868
|
const expectCall = callee.object;
|
|
13405
|
-
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) {
|
|
13406
13870
|
return null;
|
|
13407
13871
|
}
|
|
13408
13872
|
const actual = expectCall.arguments[0];
|
|
13409
|
-
if (actual === void 0 || actual.type !==
|
|
13873
|
+
if (actual === void 0 || actual.type !== AST_NODE_TYPES61.MemberExpression || actual.optional) {
|
|
13410
13874
|
return null;
|
|
13411
13875
|
}
|
|
13412
13876
|
if (!isPureReceiver(actual.object)) {
|
|
@@ -13435,7 +13899,7 @@ var prefer_whole_object_assertion_default = createRule({
|
|
|
13435
13899
|
return null;
|
|
13436
13900
|
}
|
|
13437
13901
|
const expected = call.arguments[0];
|
|
13438
|
-
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) {
|
|
13439
13903
|
return null;
|
|
13440
13904
|
}
|
|
13441
13905
|
const literal = literalText(expected, (node) => sourceCode.getText(node));
|
|
@@ -13576,7 +14040,7 @@ var prefer_whole_object_assertion_default = createRule({
|
|
|
13576
14040
|
});
|
|
13577
14041
|
|
|
13578
14042
|
// src/rules/repeated-static-call-cases.ts
|
|
13579
|
-
import { AST_NODE_TYPES as
|
|
14043
|
+
import { AST_NODE_TYPES as AST_NODE_TYPES62, ASTUtils as ASTUtils18 } from "@typescript-eslint/utils";
|
|
13580
14044
|
var REPEATED_STATIC_CALL_CASES_DOCUMENTATION = {
|
|
13581
14045
|
summary: "Report three or more consecutive literal call assertions that should be independently named test cases.",
|
|
13582
14046
|
rationale: "Copy-pasted cases obscure the input table and stop later cases from being reported after the first failure.",
|
|
@@ -13597,67 +14061,67 @@ var EXPECT_MODIFIERS = /* @__PURE__ */ new Set(["not", "rejects", "resolves"]);
|
|
|
13597
14061
|
var SNAPSHOT_MATCHERS = /snapshot/iu;
|
|
13598
14062
|
var MIN_CASES2 = 3;
|
|
13599
14063
|
function staticMemberName5(node) {
|
|
13600
|
-
if (!node.computed && node.property.type ===
|
|
13601
|
-
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;
|
|
13602
14066
|
return null;
|
|
13603
14067
|
}
|
|
13604
|
-
function
|
|
13605
|
-
const variable =
|
|
14068
|
+
function importedName6(identifier, context, modules) {
|
|
14069
|
+
const variable = ASTUtils18.findVariable(context.sourceCode.getScope(identifier), identifier.name);
|
|
13606
14070
|
if (variable === null || variable.defs.length === 0) return identifier.name;
|
|
13607
14071
|
for (const definition of variable.defs) {
|
|
13608
|
-
if (definition.node.type !==
|
|
14072
|
+
if (definition.node.type !== AST_NODE_TYPES62.ImportSpecifier) continue;
|
|
13609
14073
|
const declaration = definition.node.parent;
|
|
13610
|
-
if (declaration.type !==
|
|
14074
|
+
if (declaration.type !== AST_NODE_TYPES62.ImportDeclaration || typeof declaration.source.value !== "string" || !modules.has(declaration.source.value)) continue;
|
|
13611
14075
|
const imported = definition.node.imported;
|
|
13612
|
-
return imported.type ===
|
|
14076
|
+
return imported.type === AST_NODE_TYPES62.Identifier ? imported.name : String(imported.value);
|
|
13613
14077
|
}
|
|
13614
14078
|
return null;
|
|
13615
14079
|
}
|
|
13616
14080
|
function isDirectTestCallback2(node, context) {
|
|
13617
|
-
if (node.type !==
|
|
14081
|
+
if (node.type !== AST_NODE_TYPES62.ArrowFunctionExpression && node.type !== AST_NODE_TYPES62.FunctionExpression) return false;
|
|
13618
14082
|
const call = node.parent;
|
|
13619
|
-
if (call?.type !==
|
|
14083
|
+
if (call?.type !== AST_NODE_TYPES62.CallExpression || !call.arguments.includes(node)) return false;
|
|
13620
14084
|
const root = testRoot2(call.callee);
|
|
13621
|
-
return root !== null && TEST_NAMES2.has(
|
|
14085
|
+
return root !== null && TEST_NAMES2.has(importedName6(root, context, TEST_MODULES4) ?? "");
|
|
13622
14086
|
}
|
|
13623
14087
|
function testRoot2(callee) {
|
|
13624
|
-
if (callee.type ===
|
|
13625
|
-
if (callee.type !==
|
|
14088
|
+
if (callee.type === AST_NODE_TYPES62.Identifier) return callee;
|
|
14089
|
+
if (callee.type !== AST_NODE_TYPES62.MemberExpression) return null;
|
|
13626
14090
|
const modifier = staticMemberName5(callee);
|
|
13627
14091
|
return modifier !== null && TEST_MODIFIERS4.has(modifier) ? testRoot2(callee.object) : null;
|
|
13628
14092
|
}
|
|
13629
14093
|
function isStatic(node) {
|
|
13630
|
-
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);
|
|
13631
14095
|
switch (node.type) {
|
|
13632
|
-
case
|
|
14096
|
+
case AST_NODE_TYPES62.Literal:
|
|
13633
14097
|
return true;
|
|
13634
|
-
case
|
|
14098
|
+
case AST_NODE_TYPES62.TemplateLiteral:
|
|
13635
14099
|
return node.expressions.length === 0;
|
|
13636
|
-
case
|
|
14100
|
+
case AST_NODE_TYPES62.UnaryExpression:
|
|
13637
14101
|
return (node.operator === "+" || node.operator === "-") && isStatic(node.argument);
|
|
13638
|
-
case
|
|
13639
|
-
return node.elements.every((item) => item !== null && item.type !==
|
|
13640
|
-
case
|
|
13641
|
-
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));
|
|
13642
14106
|
default:
|
|
13643
14107
|
return false;
|
|
13644
14108
|
}
|
|
13645
14109
|
}
|
|
13646
14110
|
function staticShape(node) {
|
|
13647
|
-
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);
|
|
13648
14112
|
switch (node.type) {
|
|
13649
|
-
case
|
|
14113
|
+
case AST_NODE_TYPES62.Literal:
|
|
13650
14114
|
return `literal:${typeof node.value}`;
|
|
13651
|
-
case
|
|
14115
|
+
case AST_NODE_TYPES62.TemplateLiteral:
|
|
13652
14116
|
return "template";
|
|
13653
|
-
case
|
|
14117
|
+
case AST_NODE_TYPES62.UnaryExpression:
|
|
13654
14118
|
return `unary:${node.operator}:${staticShape(node.argument)}`;
|
|
13655
|
-
case
|
|
13656
|
-
return `array(${node.elements.map((item) => item === null || item.type ===
|
|
13657
|
-
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:
|
|
13658
14122
|
return `object(${node.properties.map((property) => {
|
|
13659
|
-
if (property.type !==
|
|
13660
|
-
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);
|
|
13661
14125
|
return `${key}:${staticShape(property.value)}`;
|
|
13662
14126
|
}).join(",")})`;
|
|
13663
14127
|
default:
|
|
@@ -13665,16 +14129,16 @@ function staticShape(node) {
|
|
|
13665
14129
|
}
|
|
13666
14130
|
}
|
|
13667
14131
|
function assertionShape(statement, context) {
|
|
13668
|
-
if (statement.type !==
|
|
14132
|
+
if (statement.type !== AST_NODE_TYPES62.ExpressionStatement || statement.expression.type !== AST_NODE_TYPES62.CallExpression) return null;
|
|
13669
14133
|
const matcherCall = statement.expression;
|
|
13670
|
-
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;
|
|
13671
14135
|
const matcher = matcherCall.callee.property.name;
|
|
13672
14136
|
if (SNAPSHOT_MATCHERS.test(matcher)) return null;
|
|
13673
14137
|
const chain = expectCallFromMatcher(matcherCall.callee);
|
|
13674
|
-
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;
|
|
13675
14139
|
const observed = chain.call.arguments[0];
|
|
13676
14140
|
const expected = matcherCall.arguments[0];
|
|
13677
|
-
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;
|
|
13678
14142
|
const skeleton = `${observed.callee.name}/${observed.arguments.map((item) => staticShape(item)).join(",")}/${chain.modifiers.join(".")}/${matcher}/${staticShape(expected)}`;
|
|
13679
14143
|
const values = [...observed.arguments, expected].map((item) => context.sourceCode.getText(item)).join("\0");
|
|
13680
14144
|
return { statement, skeleton, values };
|
|
@@ -13682,13 +14146,13 @@ function assertionShape(statement, context) {
|
|
|
13682
14146
|
function expectCallFromMatcher(node) {
|
|
13683
14147
|
const modifiers = [];
|
|
13684
14148
|
let receiver = node.object;
|
|
13685
|
-
while (receiver.type ===
|
|
14149
|
+
while (receiver.type === AST_NODE_TYPES62.MemberExpression) {
|
|
13686
14150
|
const modifier = staticMemberName5(receiver);
|
|
13687
14151
|
if (modifier === null || !EXPECT_MODIFIERS.has(modifier)) return null;
|
|
13688
14152
|
modifiers.unshift(modifier);
|
|
13689
14153
|
receiver = receiver.object;
|
|
13690
14154
|
}
|
|
13691
|
-
return receiver.type ===
|
|
14155
|
+
return receiver.type === AST_NODE_TYPES62.CallExpression ? { call: receiver, modifiers } : null;
|
|
13692
14156
|
}
|
|
13693
14157
|
var repeated_static_call_cases_default = createRule({
|
|
13694
14158
|
name: "repeated-static-call-cases",
|
|
@@ -13708,7 +14172,7 @@ var repeated_static_call_cases_default = createRule({
|
|
|
13708
14172
|
return {
|
|
13709
14173
|
"CallExpression > ArrowFunctionExpression, CallExpression > FunctionExpression"(node) {
|
|
13710
14174
|
const call = node.parent;
|
|
13711
|
-
if (call?.type ===
|
|
14175
|
+
if (call?.type === AST_NODE_TYPES62.CallExpression) {
|
|
13712
14176
|
const duplicate = duplicateTestBodyCandidate(call, sourceCode);
|
|
13713
14177
|
if (duplicate !== null && duplicate.body === node) {
|
|
13714
14178
|
const groups = duplicateGroups.get(duplicate.container) ?? /* @__PURE__ */ new Map();
|
|
@@ -13718,7 +14182,7 @@ var repeated_static_call_cases_default = createRule({
|
|
|
13718
14182
|
duplicateGroups.set(duplicate.container, groups);
|
|
13719
14183
|
}
|
|
13720
14184
|
}
|
|
13721
|
-
if (!isDirectTestCallback2(node, context) || node.body.type !==
|
|
14185
|
+
if (!isDirectTestCallback2(node, context) || node.body.type !== AST_NODE_TYPES62.BlockStatement) return;
|
|
13722
14186
|
let run = [];
|
|
13723
14187
|
const flush = () => {
|
|
13724
14188
|
if (run.length >= MIN_CASES2 && new Set(run.map((item) => item.values)).size > 1) {
|
|
@@ -13759,7 +14223,7 @@ var repeated_static_call_cases_default = createRule({
|
|
|
13759
14223
|
});
|
|
13760
14224
|
|
|
13761
14225
|
// src/rules/prefer-zod-infer.ts
|
|
13762
|
-
import { AST_NODE_TYPES as
|
|
14226
|
+
import { AST_NODE_TYPES as AST_NODE_TYPES63 } from "@typescript-eslint/utils";
|
|
13763
14227
|
var PREFER_ZOD_INFER_DOCUMENTATION = {
|
|
13764
14228
|
summary: "Derive a type from its Zod schema with `z.infer` instead of hand-writing a twin declaration beside it.",
|
|
13765
14229
|
rationale: "A derived type stays synchronized when the runtime schema changes.",
|
|
@@ -13812,47 +14276,47 @@ var ZOD_TYPE_CONSTRAINTS = /* @__PURE__ */ new Set([
|
|
|
13812
14276
|
"Schema"
|
|
13813
14277
|
]);
|
|
13814
14278
|
var LEAF_NODE_TYPES = {
|
|
13815
|
-
string: [
|
|
13816
|
-
email: [
|
|
13817
|
-
url: [
|
|
13818
|
-
uuid: [
|
|
13819
|
-
ulid: [
|
|
13820
|
-
cuid: [
|
|
13821
|
-
cuid2: [
|
|
13822
|
-
nanoid: [
|
|
13823
|
-
iso: [
|
|
13824
|
-
number: [
|
|
13825
|
-
int: [
|
|
13826
|
-
float32: [
|
|
13827
|
-
float64: [
|
|
13828
|
-
boolean: [
|
|
13829
|
-
bigint: [
|
|
13830
|
-
symbol: [
|
|
13831
|
-
any: [
|
|
13832
|
-
unknown: [
|
|
13833
|
-
never: [
|
|
13834
|
-
void: [
|
|
13835
|
-
null: [
|
|
13836
|
-
undefined: [
|
|
13837
|
-
literal: [
|
|
13838
|
-
date: [
|
|
13839
|
-
array: [
|
|
13840
|
-
tuple: [
|
|
13841
|
-
object: [
|
|
13842
|
-
strictObject: [
|
|
13843
|
-
looseObject: [
|
|
13844
|
-
record: [
|
|
13845
|
-
map: [
|
|
13846
|
-
set: [
|
|
13847
|
-
promise: [
|
|
13848
|
-
enum: [
|
|
13849
|
-
nativeEnum: [
|
|
13850
|
-
union: [
|
|
13851
|
-
discriminatedUnion: [
|
|
13852
|
-
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]
|
|
13853
14317
|
};
|
|
13854
14318
|
function primitiveLiteralKey(node) {
|
|
13855
|
-
if (node.type !==
|
|
14319
|
+
if (node.type !== AST_NODE_TYPES63.Literal) {
|
|
13856
14320
|
return null;
|
|
13857
14321
|
}
|
|
13858
14322
|
if (node.value === null) {
|
|
@@ -13884,13 +14348,13 @@ function staticZodDomain(leaf, call) {
|
|
|
13884
14348
|
}
|
|
13885
14349
|
if (leaf === "literal") {
|
|
13886
14350
|
const [argument] = call.arguments;
|
|
13887
|
-
if (argument === void 0 || argument.type ===
|
|
14351
|
+
if (argument === void 0 || argument.type === AST_NODE_TYPES63.SpreadElement) {
|
|
13888
14352
|
return null;
|
|
13889
14353
|
}
|
|
13890
|
-
if (argument.type ===
|
|
14354
|
+
if (argument.type === AST_NODE_TYPES63.ArrayExpression) {
|
|
13891
14355
|
return exactDomain(
|
|
13892
14356
|
argument.elements.map(
|
|
13893
|
-
(element) => element === null || element.type ===
|
|
14357
|
+
(element) => element === null || element.type === AST_NODE_TYPES63.SpreadElement ? null : primitiveLiteralKey(element)
|
|
13894
14358
|
)
|
|
13895
14359
|
);
|
|
13896
14360
|
}
|
|
@@ -13898,13 +14362,13 @@ function staticZodDomain(leaf, call) {
|
|
|
13898
14362
|
}
|
|
13899
14363
|
if (leaf === "enum") {
|
|
13900
14364
|
const [argument] = call.arguments;
|
|
13901
|
-
if (argument === void 0 || argument.type ===
|
|
14365
|
+
if (argument === void 0 || argument.type === AST_NODE_TYPES63.SpreadElement) {
|
|
13902
14366
|
return null;
|
|
13903
14367
|
}
|
|
13904
|
-
if (argument.type ===
|
|
14368
|
+
if (argument.type === AST_NODE_TYPES63.ArrayExpression) {
|
|
13905
14369
|
return exactDomain(
|
|
13906
14370
|
argument.elements.map((element) => {
|
|
13907
|
-
if (element === null || element.type ===
|
|
14371
|
+
if (element === null || element.type === AST_NODE_TYPES63.SpreadElement) {
|
|
13908
14372
|
return null;
|
|
13909
14373
|
}
|
|
13910
14374
|
const key = primitiveLiteralKey(element);
|
|
@@ -13912,10 +14376,10 @@ function staticZodDomain(leaf, call) {
|
|
|
13912
14376
|
})
|
|
13913
14377
|
);
|
|
13914
14378
|
}
|
|
13915
|
-
if (argument.type ===
|
|
14379
|
+
if (argument.type === AST_NODE_TYPES63.ObjectExpression) {
|
|
13916
14380
|
return exactDomain(
|
|
13917
14381
|
argument.properties.map((property) => {
|
|
13918
|
-
if (property.type !==
|
|
14382
|
+
if (property.type !== AST_NODE_TYPES63.Property || property.computed || property.kind !== "init" || property.method || property.shorthand) {
|
|
13919
14383
|
return null;
|
|
13920
14384
|
}
|
|
13921
14385
|
const key = primitiveLiteralKey(property.value);
|
|
@@ -13942,15 +14406,15 @@ function sameDomain(left, right) {
|
|
|
13942
14406
|
return true;
|
|
13943
14407
|
}
|
|
13944
14408
|
function isExportedDeclaration(node) {
|
|
13945
|
-
return node.parent?.type ===
|
|
14409
|
+
return node.parent?.type === AST_NODE_TYPES63.ExportNamedDeclaration;
|
|
13946
14410
|
}
|
|
13947
14411
|
function isModuleLevelConst(node) {
|
|
13948
14412
|
const declaration = node.parent;
|
|
13949
|
-
if (declaration.type !==
|
|
14413
|
+
if (declaration.type !== AST_NODE_TYPES63.VariableDeclaration || declaration.kind !== "const") {
|
|
13950
14414
|
return false;
|
|
13951
14415
|
}
|
|
13952
14416
|
const container = declaration.parent;
|
|
13953
|
-
return container.type ===
|
|
14417
|
+
return container.type === AST_NODE_TYPES63.Program || container.type === AST_NODE_TYPES63.ExportNamedDeclaration && container.parent.type === AST_NODE_TYPES63.Program;
|
|
13954
14418
|
}
|
|
13955
14419
|
function normalizeSchemaName(name) {
|
|
13956
14420
|
return name.replace(/Schema$/i, "").replace(/^Z(?=[A-Z])/, "").toLowerCase();
|
|
@@ -13959,20 +14423,20 @@ function normalizeTypeName(name) {
|
|
|
13959
14423
|
return name.replace(/Type$/, "").toLowerCase();
|
|
13960
14424
|
}
|
|
13961
14425
|
function unwrapNullish(annotation) {
|
|
13962
|
-
if (annotation.type !==
|
|
14426
|
+
if (annotation.type !== AST_NODE_TYPES63.TSUnionType) {
|
|
13963
14427
|
return {
|
|
13964
14428
|
core: annotation,
|
|
13965
|
-
nullable: annotation.type ===
|
|
14429
|
+
nullable: annotation.type === AST_NODE_TYPES63.TSNullKeyword
|
|
13966
14430
|
};
|
|
13967
14431
|
}
|
|
13968
14432
|
const rest = [];
|
|
13969
14433
|
let nullable = false;
|
|
13970
14434
|
for (const member of annotation.types) {
|
|
13971
|
-
if (member.type ===
|
|
14435
|
+
if (member.type === AST_NODE_TYPES63.TSNullKeyword) {
|
|
13972
14436
|
nullable = true;
|
|
13973
14437
|
continue;
|
|
13974
14438
|
}
|
|
13975
|
-
if (member.type ===
|
|
14439
|
+
if (member.type === AST_NODE_TYPES63.TSUndefinedKeyword) {
|
|
13976
14440
|
continue;
|
|
13977
14441
|
}
|
|
13978
14442
|
rest.push(member);
|
|
@@ -14006,18 +14470,18 @@ function leafAgrees(field, annotation) {
|
|
|
14006
14470
|
return null;
|
|
14007
14471
|
}
|
|
14008
14472
|
if (leaf === "date") {
|
|
14009
|
-
return core.type ===
|
|
14473
|
+
return core.type === AST_NODE_TYPES63.TSTypeReference && core.typeName.type === AST_NODE_TYPES63.Identifier && core.typeName.name === "Date";
|
|
14010
14474
|
}
|
|
14011
14475
|
return expected.includes(core.type);
|
|
14012
14476
|
}
|
|
14013
14477
|
function typeLiteralDomain(annotation) {
|
|
14014
|
-
const members = annotation.type ===
|
|
14478
|
+
const members = annotation.type === AST_NODE_TYPES63.TSUnionType ? annotation.types : [annotation];
|
|
14015
14479
|
const keys = [];
|
|
14016
14480
|
for (const member of members) {
|
|
14017
|
-
if (member.type ===
|
|
14481
|
+
if (member.type === AST_NODE_TYPES63.TSNullKeyword) {
|
|
14018
14482
|
continue;
|
|
14019
14483
|
}
|
|
14020
|
-
if (member.type !==
|
|
14484
|
+
if (member.type !== AST_NODE_TYPES63.TSLiteralType) {
|
|
14021
14485
|
return null;
|
|
14022
14486
|
}
|
|
14023
14487
|
keys.push(primitiveLiteralKey(member.literal));
|
|
@@ -14025,11 +14489,11 @@ function typeLiteralDomain(annotation) {
|
|
|
14025
14489
|
return exactDomain(keys);
|
|
14026
14490
|
}
|
|
14027
14491
|
function staticStringUnionDomain(node) {
|
|
14028
|
-
if (node.type !==
|
|
14492
|
+
if (node.type !== AST_NODE_TYPES63.TSUnionType) {
|
|
14029
14493
|
return null;
|
|
14030
14494
|
}
|
|
14031
14495
|
const keys = node.types.map((member) => {
|
|
14032
|
-
if (member.type !==
|
|
14496
|
+
if (member.type !== AST_NODE_TYPES63.TSLiteralType) {
|
|
14033
14497
|
return null;
|
|
14034
14498
|
}
|
|
14035
14499
|
const key = primitiveLiteralKey(member.literal);
|
|
@@ -14097,14 +14561,14 @@ var prefer_zod_infer_default = createRule({
|
|
|
14097
14561
|
function zodCallChain(node) {
|
|
14098
14562
|
const chain = [];
|
|
14099
14563
|
let current = node;
|
|
14100
|
-
while (current.type ===
|
|
14564
|
+
while (current.type === AST_NODE_TYPES63.CallExpression) {
|
|
14101
14565
|
const callee = current.callee;
|
|
14102
|
-
if (callee.type !==
|
|
14566
|
+
if (callee.type !== AST_NODE_TYPES63.MemberExpression || callee.computed || callee.property.type !== AST_NODE_TYPES63.Identifier) {
|
|
14103
14567
|
return null;
|
|
14104
14568
|
}
|
|
14105
14569
|
chain.push(current);
|
|
14106
14570
|
const receiver = callee.object;
|
|
14107
|
-
if (receiver.type ===
|
|
14571
|
+
if (receiver.type === AST_NODE_TYPES63.Identifier) {
|
|
14108
14572
|
return zodNamespaces.has(receiver.name) ? chain.reverse() : null;
|
|
14109
14573
|
}
|
|
14110
14574
|
current = receiver;
|
|
@@ -14113,14 +14577,14 @@ var prefer_zod_infer_default = createRule({
|
|
|
14113
14577
|
}
|
|
14114
14578
|
function methodName2(call) {
|
|
14115
14579
|
const callee = call.callee;
|
|
14116
|
-
return callee.type ===
|
|
14580
|
+
return callee.type === AST_NODE_TYPES63.MemberExpression && callee.property.type === AST_NODE_TYPES63.Identifier ? callee.property.name : "";
|
|
14117
14581
|
}
|
|
14118
14582
|
function recordZodImport(node) {
|
|
14119
14583
|
if (!isZodModule(node.source.value)) {
|
|
14120
14584
|
return;
|
|
14121
14585
|
}
|
|
14122
14586
|
for (const specifier of node.specifiers) {
|
|
14123
|
-
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") {
|
|
14124
14588
|
zodNamespaces.add(specifier.local.name);
|
|
14125
14589
|
}
|
|
14126
14590
|
}
|
|
@@ -14130,13 +14594,13 @@ var prefer_zod_infer_default = createRule({
|
|
|
14130
14594
|
let current = node;
|
|
14131
14595
|
let leaf = null;
|
|
14132
14596
|
let leafCall = null;
|
|
14133
|
-
while (current.type ===
|
|
14597
|
+
while (current.type === AST_NODE_TYPES63.CallExpression) {
|
|
14134
14598
|
const callee = current.callee;
|
|
14135
|
-
if (callee.type !==
|
|
14599
|
+
if (callee.type !== AST_NODE_TYPES63.MemberExpression || callee.computed || callee.property.type !== AST_NODE_TYPES63.Identifier) {
|
|
14136
14600
|
break;
|
|
14137
14601
|
}
|
|
14138
14602
|
const receiver = callee.object;
|
|
14139
|
-
if (receiver.type ===
|
|
14603
|
+
if (receiver.type === AST_NODE_TYPES63.Identifier && zodNamespaces.has(receiver.name)) {
|
|
14140
14604
|
leaf = callee.property.name;
|
|
14141
14605
|
leafCall = current;
|
|
14142
14606
|
break;
|
|
@@ -14167,20 +14631,20 @@ var prefer_zod_infer_default = createRule({
|
|
|
14167
14631
|
return domain instanceof Set && domain.size >= 2 ? domain : null;
|
|
14168
14632
|
}
|
|
14169
14633
|
function inferredSchemaName(node) {
|
|
14170
|
-
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") {
|
|
14171
14635
|
return null;
|
|
14172
14636
|
}
|
|
14173
14637
|
const arguments_ = node.typeArguments?.params ?? [];
|
|
14174
14638
|
const [argument] = arguments_;
|
|
14175
|
-
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;
|
|
14176
14640
|
}
|
|
14177
14641
|
function recordLiteralUnions(members, owner, ownerName, exported) {
|
|
14178
14642
|
for (const member of members) {
|
|
14179
|
-
if (member.type !==
|
|
14643
|
+
if (member.type !== AST_NODE_TYPES63.TSPropertySignature || member.computed || member.optional || member.readonly || member.typeAnnotation === void 0) {
|
|
14180
14644
|
continue;
|
|
14181
14645
|
}
|
|
14182
14646
|
const key = member.key;
|
|
14183
|
-
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;
|
|
14184
14648
|
if (propertyName5 === null) {
|
|
14185
14649
|
continue;
|
|
14186
14650
|
}
|
|
@@ -14190,7 +14654,7 @@ var prefer_zod_infer_default = createRule({
|
|
|
14190
14654
|
}
|
|
14191
14655
|
const annotation = member.typeAnnotation.typeAnnotation;
|
|
14192
14656
|
const domain = staticStringUnionDomain(annotation);
|
|
14193
|
-
if (domain === null || annotation.type !==
|
|
14657
|
+
if (domain === null || annotation.type !== AST_NODE_TYPES63.TSUnionType) {
|
|
14194
14658
|
continue;
|
|
14195
14659
|
}
|
|
14196
14660
|
literalUnionOccurrences.push({
|
|
@@ -14221,16 +14685,16 @@ var prefer_zod_infer_default = createRule({
|
|
|
14221
14685
|
return null;
|
|
14222
14686
|
}
|
|
14223
14687
|
const shape = base.arguments[0];
|
|
14224
|
-
if (shape === void 0 || shape.type !==
|
|
14688
|
+
if (shape === void 0 || shape.type !== AST_NODE_TYPES63.ObjectExpression) {
|
|
14225
14689
|
return null;
|
|
14226
14690
|
}
|
|
14227
14691
|
const fields = /* @__PURE__ */ new Map();
|
|
14228
14692
|
for (const property of shape.properties) {
|
|
14229
|
-
if (property.type !==
|
|
14693
|
+
if (property.type !== AST_NODE_TYPES63.Property || property.computed) {
|
|
14230
14694
|
return null;
|
|
14231
14695
|
}
|
|
14232
14696
|
const { key } = property;
|
|
14233
|
-
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;
|
|
14234
14698
|
if (name === null) {
|
|
14235
14699
|
return null;
|
|
14236
14700
|
}
|
|
@@ -14241,11 +14705,11 @@ var prefer_zod_infer_default = createRule({
|
|
|
14241
14705
|
function typeMembers(members) {
|
|
14242
14706
|
const result = /* @__PURE__ */ new Map();
|
|
14243
14707
|
for (const member of members) {
|
|
14244
|
-
if (member.type !==
|
|
14708
|
+
if (member.type !== AST_NODE_TYPES63.TSPropertySignature || member.computed) {
|
|
14245
14709
|
return null;
|
|
14246
14710
|
}
|
|
14247
14711
|
const { key } = member;
|
|
14248
|
-
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;
|
|
14249
14713
|
if (name === null) {
|
|
14250
14714
|
return null;
|
|
14251
14715
|
}
|
|
@@ -14260,8 +14724,8 @@ var prefer_zod_infer_default = createRule({
|
|
|
14260
14724
|
return result.size === 0 ? null : result;
|
|
14261
14725
|
}
|
|
14262
14726
|
function collectConstrainedNames(node) {
|
|
14263
|
-
if (node.type ===
|
|
14264
|
-
if (node.typeName.type ===
|
|
14727
|
+
if (node.type === AST_NODE_TYPES63.TSTypeReference) {
|
|
14728
|
+
if (node.typeName.type === AST_NODE_TYPES63.Identifier) {
|
|
14265
14729
|
constrainedTypeNames.add(node.typeName.name);
|
|
14266
14730
|
}
|
|
14267
14731
|
for (const argument of node.typeArguments?.params ?? []) {
|
|
@@ -14269,11 +14733,11 @@ var prefer_zod_infer_default = createRule({
|
|
|
14269
14733
|
}
|
|
14270
14734
|
return;
|
|
14271
14735
|
}
|
|
14272
|
-
if (node.type ===
|
|
14736
|
+
if (node.type === AST_NODE_TYPES63.TSArrayType) {
|
|
14273
14737
|
collectConstrainedNames(node.elementType);
|
|
14274
14738
|
return;
|
|
14275
14739
|
}
|
|
14276
|
-
if (node.type ===
|
|
14740
|
+
if (node.type === AST_NODE_TYPES63.TSUnionType || node.type === AST_NODE_TYPES63.TSIntersectionType) {
|
|
14277
14741
|
for (const member of node.types) {
|
|
14278
14742
|
collectConstrainedNames(member);
|
|
14279
14743
|
}
|
|
@@ -14317,7 +14781,7 @@ var prefer_zod_infer_default = createRule({
|
|
|
14317
14781
|
return {
|
|
14318
14782
|
Program(node) {
|
|
14319
14783
|
for (const statement of node.body) {
|
|
14320
|
-
if (statement.type ===
|
|
14784
|
+
if (statement.type === AST_NODE_TYPES63.ImportDeclaration) {
|
|
14321
14785
|
recordZodImport(statement);
|
|
14322
14786
|
}
|
|
14323
14787
|
}
|
|
@@ -14326,7 +14790,7 @@ var prefer_zod_infer_default = createRule({
|
|
|
14326
14790
|
recordZodImport(node);
|
|
14327
14791
|
},
|
|
14328
14792
|
VariableDeclarator(node) {
|
|
14329
|
-
if (node.id.type !==
|
|
14793
|
+
if (node.id.type !== AST_NODE_TYPES63.Identifier || node.init == null) {
|
|
14330
14794
|
return;
|
|
14331
14795
|
}
|
|
14332
14796
|
const fields = schemaFields(node.init);
|
|
@@ -14343,14 +14807,14 @@ var prefer_zod_infer_default = createRule({
|
|
|
14343
14807
|
},
|
|
14344
14808
|
/** Records `XSchema.transform(...)` and equivalent module-level reshaping. */
|
|
14345
14809
|
"MemberExpression[computed=false]"(node) {
|
|
14346
|
-
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)) {
|
|
14347
14811
|
reshapedSchemaNames.add(node.object.name);
|
|
14348
14812
|
}
|
|
14349
14813
|
},
|
|
14350
14814
|
/** Records every type argument carried by a Zod constraint. */
|
|
14351
14815
|
TSTypeReference(node) {
|
|
14352
14816
|
const { typeName } = node;
|
|
14353
|
-
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;
|
|
14354
14818
|
if (referenced === null || !ZOD_TYPE_CONSTRAINTS.has(referenced)) {
|
|
14355
14819
|
return;
|
|
14356
14820
|
}
|
|
@@ -14382,7 +14846,7 @@ var prefer_zod_infer_default = createRule({
|
|
|
14382
14846
|
typeName: node.id.name
|
|
14383
14847
|
});
|
|
14384
14848
|
}
|
|
14385
|
-
if (node.typeParameters !== void 0 || node.typeAnnotation.type !==
|
|
14849
|
+
if (node.typeParameters !== void 0 || node.typeAnnotation.type !== AST_NODE_TYPES63.TSTypeLiteral) {
|
|
14386
14850
|
return;
|
|
14387
14851
|
}
|
|
14388
14852
|
const members = typeMembers(node.typeAnnotation.members);
|
|
@@ -14482,10 +14946,10 @@ var prefer_zod_infer_default = createRule({
|
|
|
14482
14946
|
|
|
14483
14947
|
// src/rules/require-assert-never.ts
|
|
14484
14948
|
import {
|
|
14485
|
-
ESLintUtils as
|
|
14486
|
-
AST_NODE_TYPES as
|
|
14949
|
+
ESLintUtils as ESLintUtils7,
|
|
14950
|
+
AST_NODE_TYPES as AST_NODE_TYPES64
|
|
14487
14951
|
} from "@typescript-eslint/utils";
|
|
14488
|
-
import
|
|
14952
|
+
import ts5 from "typescript";
|
|
14489
14953
|
var REQUIRE_ASSERT_NEVER_DOCUMENTATION = {
|
|
14490
14954
|
summary: "Require an empty switch default to call `assertNever` so discriminated unions remain exhaustive at compile time.",
|
|
14491
14955
|
rationale: "An empty default silently accepts new union members instead of making the compiler identify the missing case.",
|
|
@@ -14497,14 +14961,14 @@ var REQUIRE_ASSERT_NEVER_DOCUMENTATION = {
|
|
|
14497
14961
|
]
|
|
14498
14962
|
};
|
|
14499
14963
|
var isRuntimeHandlingStatement = (statement) => {
|
|
14500
|
-
if (statement.type ===
|
|
14501
|
-
if (statement.type ===
|
|
14964
|
+
if (statement.type === AST_NODE_TYPES64.EmptyStatement) return false;
|
|
14965
|
+
if (statement.type === AST_NODE_TYPES64.BreakStatement) {
|
|
14502
14966
|
return statement.label !== null;
|
|
14503
14967
|
}
|
|
14504
|
-
if (statement.type ===
|
|
14968
|
+
if (statement.type === AST_NODE_TYPES64.TSTypeAliasDeclaration || statement.type === AST_NODE_TYPES64.TSInterfaceDeclaration) {
|
|
14505
14969
|
return false;
|
|
14506
14970
|
}
|
|
14507
|
-
if (statement.type ===
|
|
14971
|
+
if (statement.type === AST_NODE_TYPES64.BlockStatement) {
|
|
14508
14972
|
return statement.body.some(isRuntimeHandlingStatement);
|
|
14509
14973
|
}
|
|
14510
14974
|
return true;
|
|
@@ -14520,7 +14984,7 @@ var isCommentOnlyNoopDefault = (defaultCase, sourceCode) => {
|
|
|
14520
14984
|
return colonToken !== null && sourceCode.getCommentsAfter(colonToken).length > 0;
|
|
14521
14985
|
}
|
|
14522
14986
|
const only = defaultCase.consequent[0];
|
|
14523
|
-
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)) {
|
|
14524
14988
|
return sourceCode.getCommentsInside(only).length > 0;
|
|
14525
14989
|
}
|
|
14526
14990
|
return false;
|
|
@@ -14532,7 +14996,7 @@ function isExhaustiveFiniteSwitch(node, services) {
|
|
|
14532
14996
|
const constituents = discriminantType.isUnion() ? discriminantType.types : [discriminantType];
|
|
14533
14997
|
if (!discriminantType.isUnion() || constituents.length < 2) return false;
|
|
14534
14998
|
if (constituents.every(
|
|
14535
|
-
(constituent) => (constituent.flags &
|
|
14999
|
+
(constituent) => (constituent.flags & ts5.TypeFlags.BooleanLiteral) !== 0
|
|
14536
15000
|
)) {
|
|
14537
15001
|
return false;
|
|
14538
15002
|
}
|
|
@@ -14556,7 +15020,7 @@ function isExhaustiveFiniteSwitch(node, services) {
|
|
|
14556
15020
|
return [...expected].every((key) => handled.has(key));
|
|
14557
15021
|
}
|
|
14558
15022
|
function finiteTypeKey(type, checker) {
|
|
14559
|
-
const finiteFlags =
|
|
15023
|
+
const finiteFlags = ts5.TypeFlags.StringLiteral | ts5.TypeFlags.NumberLiteral | ts5.TypeFlags.BooleanLiteral | ts5.TypeFlags.EnumLiteral | ts5.TypeFlags.UniqueESSymbol | ts5.TypeFlags.Null | ts5.TypeFlags.Undefined;
|
|
14560
15024
|
return (type.flags & finiteFlags) !== 0 ? checker.typeToString(type) : null;
|
|
14561
15025
|
}
|
|
14562
15026
|
var require_assert_never_default = createRule({
|
|
@@ -14576,7 +15040,7 @@ var require_assert_never_default = createRule({
|
|
|
14576
15040
|
create(context) {
|
|
14577
15041
|
let services;
|
|
14578
15042
|
try {
|
|
14579
|
-
services =
|
|
15043
|
+
services = ESLintUtils7.getParserServices(context);
|
|
14580
15044
|
} catch {
|
|
14581
15045
|
services = null;
|
|
14582
15046
|
}
|
|
@@ -14603,7 +15067,7 @@ var require_assert_never_default = createRule({
|
|
|
14603
15067
|
});
|
|
14604
15068
|
|
|
14605
15069
|
// src/rules/require-fetch-timeout.ts
|
|
14606
|
-
import { AST_NODE_TYPES as
|
|
15070
|
+
import { AST_NODE_TYPES as AST_NODE_TYPES65, ASTUtils as ASTUtils19 } from "@typescript-eslint/utils";
|
|
14607
15071
|
var REQUIRE_FETCH_TIMEOUT_DOCUMENTATION = {
|
|
14608
15072
|
summary: "Require an abort `signal` (e.g. `AbortSignal.timeout(ms)`) on global `fetch()` calls so stalled upstreams cannot hang the caller forever.",
|
|
14609
15073
|
rationale: "An unbounded request can occupy work indefinitely when an upstream stalls.",
|
|
@@ -14629,14 +15093,14 @@ function matchesAnyPattern3(filename, patterns) {
|
|
|
14629
15093
|
return false;
|
|
14630
15094
|
}
|
|
14631
15095
|
function initProvablyLacksSignal(init) {
|
|
14632
|
-
if (init.type !==
|
|
15096
|
+
if (init.type !== AST_NODE_TYPES65.ObjectExpression) {
|
|
14633
15097
|
return false;
|
|
14634
15098
|
}
|
|
14635
15099
|
for (const prop of init.properties) {
|
|
14636
|
-
if (prop.type ===
|
|
15100
|
+
if (prop.type === AST_NODE_TYPES65.SpreadElement) {
|
|
14637
15101
|
return false;
|
|
14638
15102
|
}
|
|
14639
|
-
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") {
|
|
14640
15104
|
return false;
|
|
14641
15105
|
}
|
|
14642
15106
|
if (prop.computed) {
|
|
@@ -14646,7 +15110,7 @@ function initProvablyLacksSignal(init) {
|
|
|
14646
15110
|
return true;
|
|
14647
15111
|
}
|
|
14648
15112
|
function isInlineUrl(node, resolvesToGlobal) {
|
|
14649
|
-
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);
|
|
14650
15114
|
}
|
|
14651
15115
|
var require_fetch_timeout_default = createRule({
|
|
14652
15116
|
name: "require-fetch-timeout",
|
|
@@ -14684,30 +15148,30 @@ var require_fetch_timeout_default = createRule({
|
|
|
14684
15148
|
}
|
|
14685
15149
|
function resolvesToGlobal(identifier) {
|
|
14686
15150
|
const scope = context.sourceCode.getScope(identifier);
|
|
14687
|
-
const variable =
|
|
15151
|
+
const variable = ASTUtils19.findVariable(scope, identifier.name);
|
|
14688
15152
|
return variable === null || variable.defs.length === 0;
|
|
14689
15153
|
}
|
|
14690
15154
|
function isGlobalFetchCall2(callee) {
|
|
14691
|
-
if (callee.type ===
|
|
15155
|
+
if (callee.type === AST_NODE_TYPES65.Identifier) {
|
|
14692
15156
|
return callee.name === "fetch" && resolvesToGlobal(callee);
|
|
14693
15157
|
}
|
|
14694
|
-
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);
|
|
14695
15159
|
}
|
|
14696
15160
|
function localConstInitProvablyLacksSignal(identifier) {
|
|
14697
|
-
const variable =
|
|
15161
|
+
const variable = ASTUtils19.findVariable(
|
|
14698
15162
|
context.sourceCode.getScope(identifier),
|
|
14699
15163
|
identifier.name
|
|
14700
15164
|
);
|
|
14701
15165
|
if (variable?.defs.length !== 1) return false;
|
|
14702
15166
|
const definition = variable.defs[0];
|
|
14703
|
-
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)) {
|
|
14704
15168
|
return false;
|
|
14705
15169
|
}
|
|
14706
15170
|
for (const reference of variable.references) {
|
|
14707
15171
|
const ref = reference.identifier;
|
|
14708
15172
|
if (ref === identifier || ref === definition.name) continue;
|
|
14709
15173
|
const member = ref.parent;
|
|
14710
|
-
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) {
|
|
14711
15175
|
return false;
|
|
14712
15176
|
}
|
|
14713
15177
|
}
|
|
@@ -14722,7 +15186,7 @@ var require_fetch_timeout_default = createRule({
|
|
|
14722
15186
|
if (node.arguments.length === 1 && first !== void 0 && !isInlineUrl(first, resolvesToGlobal)) {
|
|
14723
15187
|
return;
|
|
14724
15188
|
}
|
|
14725
|
-
if (init === void 0 || initProvablyLacksSignal(init) || init.type ===
|
|
15189
|
+
if (init === void 0 || initProvablyLacksSignal(init) || init.type === AST_NODE_TYPES65.Identifier && localConstInitProvablyLacksSignal(init)) {
|
|
14726
15190
|
context.report({ node, messageId: "missingSignal" });
|
|
14727
15191
|
}
|
|
14728
15192
|
}
|
|
@@ -14731,7 +15195,7 @@ var require_fetch_timeout_default = createRule({
|
|
|
14731
15195
|
});
|
|
14732
15196
|
|
|
14733
15197
|
// src/rules/require-port-for-service.ts
|
|
14734
|
-
import { AST_NODE_TYPES as
|
|
15198
|
+
import { AST_NODE_TYPES as AST_NODE_TYPES66 } from "@typescript-eslint/utils";
|
|
14735
15199
|
var REQUIRE_PORT_FOR_SERVICE_DOCUMENTATION = {
|
|
14736
15200
|
summary: "Advise when an exported service with injected collaborators has public methods not covered by its declared ports.",
|
|
14737
15201
|
rationale: "A declared port keeps consumers coupled to the service capability instead of its concrete implementation.",
|
|
@@ -14756,45 +15220,45 @@ var ROUTER_FACTORY_NAME = "Router";
|
|
|
14756
15220
|
var FRAMEWORK_HTTP_TYPES = /* @__PURE__ */ new Set(["Request", "Response", "NextFunction"]);
|
|
14757
15221
|
var STORAGE_ASSIGNMENT_OPERATORS = /* @__PURE__ */ new Set(["=", "&&=", "??=", "||="]);
|
|
14758
15222
|
var staticMemberName6 = (member) => {
|
|
14759
|
-
if (member.property.type ===
|
|
14760
|
-
if (!member.computed && member.property.type ===
|
|
14761
|
-
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;
|
|
14762
15226
|
};
|
|
14763
15227
|
var detachedValueExports = (program) => {
|
|
14764
15228
|
const names = /* @__PURE__ */ new Set();
|
|
14765
15229
|
for (const statement of program.body) {
|
|
14766
|
-
if (statement.type ===
|
|
15230
|
+
if (statement.type === AST_NODE_TYPES66.ExportNamedDeclaration && statement.declaration === null && statement.source === null && statement.exportKind !== "type") {
|
|
14767
15231
|
for (const specifier of statement.specifiers) {
|
|
14768
15232
|
if (specifier.exportKind !== "type") names.add(specifier.local.name);
|
|
14769
15233
|
}
|
|
14770
|
-
} else if (statement.type ===
|
|
15234
|
+
} else if (statement.type === AST_NODE_TYPES66.ExportDefaultDeclaration && statement.declaration.type === AST_NODE_TYPES66.Identifier) {
|
|
14771
15235
|
names.add(statement.declaration.name);
|
|
14772
|
-
} else if (statement.type ===
|
|
15236
|
+
} else if (statement.type === AST_NODE_TYPES66.TSExportAssignment && statement.expression.type === AST_NODE_TYPES66.Identifier) {
|
|
14773
15237
|
names.add(statement.expression.name);
|
|
14774
15238
|
}
|
|
14775
15239
|
}
|
|
14776
15240
|
return names;
|
|
14777
15241
|
};
|
|
14778
|
-
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);
|
|
14779
15243
|
var readTypeReference = (annotation) => {
|
|
14780
|
-
if (annotation?.type ===
|
|
15244
|
+
if (annotation?.type === AST_NODE_TYPES66.TSUnionType) {
|
|
14781
15245
|
const members = annotation.types.filter(
|
|
14782
|
-
(member) => member.type !==
|
|
15246
|
+
(member) => member.type !== AST_NODE_TYPES66.TSUndefinedKeyword && member.type !== AST_NODE_TYPES66.TSNullKeyword
|
|
14783
15247
|
);
|
|
14784
15248
|
annotation = members.length === 1 ? members[0] : void 0;
|
|
14785
15249
|
}
|
|
14786
|
-
if (annotation === void 0 || annotation.type !==
|
|
15250
|
+
if (annotation === void 0 || annotation.type !== AST_NODE_TYPES66.TSTypeReference) return null;
|
|
14787
15251
|
const { typeName } = annotation;
|
|
14788
|
-
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;
|
|
14789
15253
|
if (rightmost === null) return null;
|
|
14790
15254
|
return { typeName: rightmost, display: qualifiedName(typeName) };
|
|
14791
15255
|
};
|
|
14792
|
-
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}` : "";
|
|
14793
15257
|
var propertySignatureTypes = (members) => {
|
|
14794
15258
|
const types = /* @__PURE__ */ new Map();
|
|
14795
15259
|
for (const member of members) {
|
|
14796
|
-
if (member.type !==
|
|
14797
|
-
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;
|
|
14798
15262
|
const reference = readTypeReference(member.typeAnnotation?.typeAnnotation);
|
|
14799
15263
|
if (reference === null) continue;
|
|
14800
15264
|
types.set(member.key.name, reference);
|
|
@@ -14805,18 +15269,18 @@ var fileTypeIndex = (program) => {
|
|
|
14805
15269
|
const objects = /* @__PURE__ */ new Map();
|
|
14806
15270
|
const functionAliases = /* @__PURE__ */ new Set();
|
|
14807
15271
|
for (const statement of program.body) {
|
|
14808
|
-
const declaration = statement.type ===
|
|
14809
|
-
if (declaration?.type ===
|
|
15272
|
+
const declaration = statement.type === AST_NODE_TYPES66.ExportNamedDeclaration ? statement.declaration : statement;
|
|
15273
|
+
if (declaration?.type === AST_NODE_TYPES66.TSInterfaceDeclaration) {
|
|
14810
15274
|
objects.set(declaration.id.name, propertySignatureTypes(declaration.body.body));
|
|
14811
15275
|
continue;
|
|
14812
15276
|
}
|
|
14813
|
-
if (declaration?.type !==
|
|
15277
|
+
if (declaration?.type !== AST_NODE_TYPES66.TSTypeAliasDeclaration) continue;
|
|
14814
15278
|
const aliased = declaration.typeAnnotation;
|
|
14815
|
-
if (aliased.type ===
|
|
15279
|
+
if (aliased.type === AST_NODE_TYPES66.TSFunctionType || aliased.type === AST_NODE_TYPES66.TSConstructorType) {
|
|
14816
15280
|
functionAliases.add(declaration.id.name);
|
|
14817
15281
|
continue;
|
|
14818
15282
|
}
|
|
14819
|
-
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) : [];
|
|
14820
15284
|
if (literals.length === 0) continue;
|
|
14821
15285
|
const merged = /* @__PURE__ */ new Map();
|
|
14822
15286
|
for (const literal of literals) {
|
|
@@ -14845,10 +15309,10 @@ var readConstructor = (ctor, declared, typeParameters) => {
|
|
|
14845
15309
|
while (pending.length > 0) {
|
|
14846
15310
|
const current = pending.pop();
|
|
14847
15311
|
if (current === void 0) break;
|
|
14848
|
-
if (current.type ===
|
|
14849
|
-
const expression = current.type ===
|
|
14850
|
-
const storedField = expression?.type ===
|
|
14851
|
-
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) {
|
|
14852
15316
|
for (const key of Object.keys(current)) {
|
|
14853
15317
|
if (key === "parent") continue;
|
|
14854
15318
|
const value = current[key];
|
|
@@ -14861,14 +15325,14 @@ var readConstructor = (ctor, declared, typeParameters) => {
|
|
|
14861
15325
|
continue;
|
|
14862
15326
|
}
|
|
14863
15327
|
let source = expression.right;
|
|
14864
|
-
while (source.type ===
|
|
14865
|
-
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) {
|
|
14866
15330
|
constructedFields += 1;
|
|
14867
|
-
} else if (source.type ===
|
|
15331
|
+
} else if (source.type === AST_NODE_TYPES66.Identifier) {
|
|
14868
15332
|
const fields = storedFieldsFrom.get(source.name) ?? /* @__PURE__ */ new Set();
|
|
14869
15333
|
fields.add(storedField);
|
|
14870
15334
|
storedFieldsFrom.set(source.name, fields);
|
|
14871
|
-
} else if (source.type ===
|
|
15335
|
+
} else if (source.type === AST_NODE_TYPES66.MemberExpression && source.object.type === AST_NODE_TYPES66.Identifier) {
|
|
14872
15336
|
const fields = storedFieldsFrom.get(source.object.name) ?? /* @__PURE__ */ new Set();
|
|
14873
15337
|
fields.add(storedField);
|
|
14874
15338
|
storedFieldsFrom.set(source.object.name, fields);
|
|
@@ -14886,7 +15350,7 @@ var readConstructor = (ctor, declared, typeParameters) => {
|
|
|
14886
15350
|
const collaborators = [];
|
|
14887
15351
|
for (const parameter of ctor.value.params) {
|
|
14888
15352
|
for (const reference of parameterCollaborators(parameter, declared, storedMemberFieldsFrom)) {
|
|
14889
|
-
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) ?? []];
|
|
14890
15354
|
if (fields.length === 0) continue;
|
|
14891
15355
|
if (CONFIGISH_TYPE_RE.test(reference.typeName)) continue;
|
|
14892
15356
|
if (CONFIGISH_NAME_RE.test(reference.name)) continue;
|
|
@@ -14901,8 +15365,8 @@ var readConstructor = (ctor, declared, typeParameters) => {
|
|
|
14901
15365
|
};
|
|
14902
15366
|
var parameterCollaborators = (parameter, declared, storedMemberFieldsFrom) => {
|
|
14903
15367
|
let target = parameter;
|
|
14904
|
-
if (target.type ===
|
|
14905
|
-
if (target.type ===
|
|
15368
|
+
if (target.type === AST_NODE_TYPES66.AssignmentPattern) target = target.left;
|
|
15369
|
+
if (target.type === AST_NODE_TYPES66.ObjectPattern) {
|
|
14906
15370
|
return objectPatternCollaborators(target, declared);
|
|
14907
15371
|
}
|
|
14908
15372
|
const named2 = namedParameterCollaborator(parameter);
|
|
@@ -14911,9 +15375,9 @@ var parameterCollaborators = (parameter, declared, storedMemberFieldsFrom) => {
|
|
|
14911
15375
|
};
|
|
14912
15376
|
var namedBagCollaborators = (annotated, declared, storedMemberFieldsFrom) => {
|
|
14913
15377
|
let target = annotated;
|
|
14914
|
-
if (target.type ===
|
|
14915
|
-
if (target.type ===
|
|
14916
|
-
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 [];
|
|
14917
15381
|
const members = bagMemberTypes(target.typeAnnotation?.typeAnnotation, declared);
|
|
14918
15382
|
if (members === null) return [];
|
|
14919
15383
|
const storedMembers = storedMemberFieldsFrom.get(target.name);
|
|
@@ -14929,9 +15393,9 @@ var namedBagCollaborators = (annotated, declared, storedMemberFieldsFrom) => {
|
|
|
14929
15393
|
};
|
|
14930
15394
|
var namedParameterCollaborator = (annotated) => {
|
|
14931
15395
|
let target = annotated;
|
|
14932
|
-
if (target.type ===
|
|
14933
|
-
if (target.type ===
|
|
14934
|
-
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;
|
|
14935
15399
|
const reference = readTypeReference(target.typeAnnotation?.typeAnnotation);
|
|
14936
15400
|
if (reference === null) return null;
|
|
14937
15401
|
return { name: target.name, ...reference, fields: [] };
|
|
@@ -14943,11 +15407,11 @@ var objectPatternCollaborators = (pattern, declared) => {
|
|
|
14943
15407
|
if (members === null) return [];
|
|
14944
15408
|
const collaborators = [];
|
|
14945
15409
|
for (const property of pattern.properties) {
|
|
14946
|
-
if (property.type !==
|
|
14947
|
-
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;
|
|
14948
15412
|
const key = property.key.name;
|
|
14949
|
-
const bound = property.value.type ===
|
|
14950
|
-
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;
|
|
14951
15415
|
if (CONFIGISH_NAME_RE.test(key)) continue;
|
|
14952
15416
|
const reference = members.get(key);
|
|
14953
15417
|
if (reference === void 0) continue;
|
|
@@ -14957,21 +15421,21 @@ var objectPatternCollaborators = (pattern, declared) => {
|
|
|
14957
15421
|
};
|
|
14958
15422
|
var bagMemberTypes = (annotation, declared) => {
|
|
14959
15423
|
if (annotation === void 0) return null;
|
|
14960
|
-
if (annotation.type ===
|
|
15424
|
+
if (annotation.type === AST_NODE_TYPES66.TSTypeLiteral) {
|
|
14961
15425
|
return propertySignatureTypes(annotation.members);
|
|
14962
15426
|
}
|
|
14963
|
-
if (annotation.type !==
|
|
15427
|
+
if (annotation.type !== AST_NODE_TYPES66.TSTypeReference || annotation.typeName.type !== AST_NODE_TYPES66.Identifier) {
|
|
14964
15428
|
return null;
|
|
14965
15429
|
}
|
|
14966
15430
|
return declared().objects.get(annotation.typeName.name) ?? null;
|
|
14967
15431
|
};
|
|
14968
15432
|
var isFrameworkWiring = (body2) => subtreeHas(body2, (node) => {
|
|
14969
|
-
if (node.type ===
|
|
15433
|
+
if (node.type === AST_NODE_TYPES66.CallExpression) {
|
|
14970
15434
|
const { callee } = node;
|
|
14971
|
-
if (callee.type ===
|
|
14972
|
-
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;
|
|
14973
15437
|
}
|
|
14974
|
-
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);
|
|
14975
15439
|
});
|
|
14976
15440
|
var subtreeHas = (root, found) => {
|
|
14977
15441
|
let hit = false;
|
|
@@ -14998,19 +15462,19 @@ var invokedInstanceField = (call) => {
|
|
|
14998
15462
|
const direct = instanceField(call.callee);
|
|
14999
15463
|
if (direct !== null) return direct;
|
|
15000
15464
|
let callee = call.callee;
|
|
15001
|
-
while (callee.type ===
|
|
15002
|
-
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;
|
|
15003
15467
|
};
|
|
15004
15468
|
var instanceField = (candidate2) => {
|
|
15005
15469
|
let node = candidate2;
|
|
15006
|
-
while (node.type ===
|
|
15007
|
-
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;
|
|
15008
15472
|
};
|
|
15009
15473
|
var behaviorallyInvokedFields = (body2) => {
|
|
15010
15474
|
const invoked = /* @__PURE__ */ new Set();
|
|
15011
15475
|
const visit = (current) => {
|
|
15012
|
-
if (current.type ===
|
|
15013
|
-
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) {
|
|
15014
15478
|
const field = invokedInstanceField(current);
|
|
15015
15479
|
if (field !== null) invoked.add(field);
|
|
15016
15480
|
}
|
|
@@ -15023,14 +15487,14 @@ var behaviorallyInvokedFields = (body2) => {
|
|
|
15023
15487
|
}
|
|
15024
15488
|
};
|
|
15025
15489
|
for (const member of body2.body) {
|
|
15026
|
-
if (member.type ===
|
|
15027
|
-
if (member.type ===
|
|
15490
|
+
if (member.type === AST_NODE_TYPES66.StaticBlock || member.static) continue;
|
|
15491
|
+
if (member.type === AST_NODE_TYPES66.MethodDefinition) {
|
|
15028
15492
|
if (member.value.body !== null && member.value.body !== void 0) visit(member.value.body);
|
|
15029
15493
|
continue;
|
|
15030
15494
|
}
|
|
15031
|
-
if (member.type !==
|
|
15495
|
+
if (member.type !== AST_NODE_TYPES66.PropertyDefinition || member.value === null) continue;
|
|
15032
15496
|
visit(
|
|
15033
|
-
member.value.type ===
|
|
15497
|
+
member.value.type === AST_NODE_TYPES66.ArrowFunctionExpression ? member.value.body : member.value
|
|
15034
15498
|
);
|
|
15035
15499
|
}
|
|
15036
15500
|
return invoked;
|
|
@@ -15050,25 +15514,26 @@ var isTransportWrapper = (className, collaborators, program) => {
|
|
|
15050
15514
|
var fileInterfaceNames = (program) => {
|
|
15051
15515
|
const names = [];
|
|
15052
15516
|
for (const statement of program.body) {
|
|
15053
|
-
const declaration = statement.type ===
|
|
15054
|
-
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);
|
|
15055
15519
|
}
|
|
15056
15520
|
return names;
|
|
15057
15521
|
};
|
|
15058
15522
|
var publicMethodNames = (body2, functionAliases) => {
|
|
15059
15523
|
const names = [];
|
|
15060
15524
|
for (const member of body2.body) {
|
|
15061
|
-
if (member.type ===
|
|
15525
|
+
if (member.type === AST_NODE_TYPES66.PropertyDefinition) {
|
|
15062
15526
|
if (member.static || member.accessibility === "private" || member.accessibility === "protected") continue;
|
|
15063
|
-
if (member.
|
|
15064
|
-
|
|
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");
|
|
15065
15530
|
continue;
|
|
15066
15531
|
}
|
|
15067
|
-
if (member.type !==
|
|
15532
|
+
if (member.type !== AST_NODE_TYPES66.MethodDefinition) continue;
|
|
15068
15533
|
if (member.kind !== "method" || member.static) continue;
|
|
15069
15534
|
if (member.accessibility === "private" || member.accessibility === "protected") continue;
|
|
15070
|
-
if (member.key.type ===
|
|
15071
|
-
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);
|
|
15072
15537
|
else names.push("\u2026");
|
|
15073
15538
|
}
|
|
15074
15539
|
return names;
|
|
@@ -15076,13 +15541,13 @@ var publicMethodNames = (body2, functionAliases) => {
|
|
|
15076
15541
|
var isFluentConstructionObject = (node, getText) => {
|
|
15077
15542
|
if (node.id === null) return false;
|
|
15078
15543
|
const methods = node.body.body.filter(
|
|
15079
|
-
(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
|
|
15080
15545
|
);
|
|
15081
15546
|
if (methods.length === 0) return false;
|
|
15082
15547
|
return methods.every((member) => {
|
|
15083
15548
|
const result = member.value.returnType?.typeAnnotation;
|
|
15084
15549
|
if (result === void 0) return false;
|
|
15085
|
-
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;
|
|
15086
15551
|
return returnsOwnType || FLUENT_BUILDER_NAME_RE.test(node.id?.name ?? "") && FLUENT_RESULT_TYPE_RE.test(getText(result));
|
|
15087
15552
|
});
|
|
15088
15553
|
};
|
|
@@ -15090,10 +15555,10 @@ function localClassAbstractness(program) {
|
|
|
15090
15555
|
const classes = /* @__PURE__ */ new Map();
|
|
15091
15556
|
const parents = /* @__PURE__ */ new Map();
|
|
15092
15557
|
for (const statement of program.body) {
|
|
15093
|
-
const declaration = statement.type ===
|
|
15094
|
-
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) {
|
|
15095
15560
|
classes.set(declaration.id.name, declaration.abstract === true);
|
|
15096
|
-
if (declaration.superClass?.type ===
|
|
15561
|
+
if (declaration.superClass?.type === AST_NODE_TYPES66.Identifier) {
|
|
15097
15562
|
parents.set(declaration.id.name, declaration.superClass.name);
|
|
15098
15563
|
}
|
|
15099
15564
|
}
|
|
@@ -15115,43 +15580,43 @@ function localInterfaceSurfaces(program) {
|
|
|
15115
15580
|
const parents = /* @__PURE__ */ new Map();
|
|
15116
15581
|
const functionAliases = /* @__PURE__ */ new Set();
|
|
15117
15582
|
for (const statement of program.body) {
|
|
15118
|
-
const declaration = statement.type ===
|
|
15119
|
-
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);
|
|
15120
15585
|
}
|
|
15121
15586
|
for (const statement of program.body) {
|
|
15122
|
-
const declaration = statement.type ===
|
|
15123
|
-
if (declaration?.type ===
|
|
15587
|
+
const declaration = statement.type === AST_NODE_TYPES66.ExportNamedDeclaration ? statement.declaration : statement;
|
|
15588
|
+
if (declaration?.type === AST_NODE_TYPES66.TSTypeAliasDeclaration) {
|
|
15124
15589
|
const callables2 = interfaces.get(declaration.id.name) ?? /* @__PURE__ */ new Set();
|
|
15125
|
-
const parts = declaration.typeAnnotation.type ===
|
|
15590
|
+
const parts = declaration.typeAnnotation.type === AST_NODE_TYPES66.TSIntersectionType ? declaration.typeAnnotation.types : [declaration.typeAnnotation];
|
|
15126
15591
|
const inherited = parents.get(declaration.id.name) ?? [];
|
|
15127
15592
|
for (const part of parts) {
|
|
15128
|
-
if (part.type ===
|
|
15593
|
+
if (part.type === AST_NODE_TYPES66.TSTypeReference && part.typeName.type === AST_NODE_TYPES66.Identifier) {
|
|
15129
15594
|
inherited.push(part.typeName.name);
|
|
15130
15595
|
continue;
|
|
15131
15596
|
}
|
|
15132
|
-
if (part.type !==
|
|
15597
|
+
if (part.type !== AST_NODE_TYPES66.TSTypeLiteral) continue;
|
|
15133
15598
|
for (const member of part.members) {
|
|
15134
|
-
if (member.type !==
|
|
15135
|
-
if (member.computed || member.key.type !==
|
|
15136
|
-
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) {
|
|
15137
15602
|
callables2.add(member.key.name);
|
|
15138
15603
|
continue;
|
|
15139
15604
|
}
|
|
15140
|
-
if (member.type !==
|
|
15605
|
+
if (member.type !== AST_NODE_TYPES66.TSPropertySignature) continue;
|
|
15141
15606
|
const annotation = member.typeAnnotation?.typeAnnotation;
|
|
15142
|
-
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);
|
|
15143
15608
|
}
|
|
15144
15609
|
}
|
|
15145
15610
|
interfaces.set(declaration.id.name, callables2);
|
|
15146
15611
|
parents.set(declaration.id.name, inherited);
|
|
15147
15612
|
continue;
|
|
15148
15613
|
}
|
|
15149
|
-
if (declaration?.type !==
|
|
15614
|
+
if (declaration?.type !== AST_NODE_TYPES66.TSInterfaceDeclaration) continue;
|
|
15150
15615
|
const callables = interfaces.get(declaration.id.name) ?? /* @__PURE__ */ new Set();
|
|
15151
15616
|
for (const member of declaration.body.body) {
|
|
15152
|
-
if (member.type !==
|
|
15153
|
-
if (member.computed || member.key.type !==
|
|
15154
|
-
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);
|
|
15155
15620
|
}
|
|
15156
15621
|
interfaces.set(declaration.id.name, callables);
|
|
15157
15622
|
parents.set(
|
|
@@ -15159,7 +15624,7 @@ function localInterfaceSurfaces(program) {
|
|
|
15159
15624
|
[
|
|
15160
15625
|
...parents.get(declaration.id.name) ?? [],
|
|
15161
15626
|
...declaration.extends.flatMap(
|
|
15162
|
-
(heritage) => heritage.expression.type ===
|
|
15627
|
+
(heritage) => heritage.expression.type === AST_NODE_TYPES66.Identifier ? [heritage.expression.name] : ["*"]
|
|
15163
15628
|
)
|
|
15164
15629
|
]
|
|
15165
15630
|
);
|
|
@@ -15186,7 +15651,7 @@ function localInterfaceSurfaces(program) {
|
|
|
15186
15651
|
}
|
|
15187
15652
|
function hasServicePort(node, methods, classes, interfaces) {
|
|
15188
15653
|
if (node.superClass !== null) {
|
|
15189
|
-
if (node.superClass.type !==
|
|
15654
|
+
if (node.superClass.type !== AST_NODE_TYPES66.Identifier) return true;
|
|
15190
15655
|
const localAbstract = classes.get(node.superClass.name);
|
|
15191
15656
|
if (localAbstract === void 0 || localAbstract) return true;
|
|
15192
15657
|
}
|
|
@@ -15198,7 +15663,7 @@ function hasServicePort(node, methods, classes, interfaces) {
|
|
|
15198
15663
|
if (node.implements.length === 0) return false;
|
|
15199
15664
|
const combined = /* @__PURE__ */ new Set();
|
|
15200
15665
|
for (const implementation of node.implements) {
|
|
15201
|
-
if (implementation.expression.type !==
|
|
15666
|
+
if (implementation.expression.type !== AST_NODE_TYPES66.Identifier) return true;
|
|
15202
15667
|
const name = implementation.expression.name;
|
|
15203
15668
|
const localAbstract = classes.get(name);
|
|
15204
15669
|
if (localAbstract === true) return true;
|
|
@@ -15241,7 +15706,7 @@ var require_port_for_service_default = createRule({
|
|
|
15241
15706
|
if (node.abstract === true) return;
|
|
15242
15707
|
if (node.decorators.length > 0) return;
|
|
15243
15708
|
const ctor = node.body.body.find(
|
|
15244
|
-
(member) => member.type ===
|
|
15709
|
+
(member) => member.type === AST_NODE_TYPES66.MethodDefinition && member.kind === "constructor" && member.value.body !== null && member.value.body !== void 0
|
|
15245
15710
|
);
|
|
15246
15711
|
if (ctor === void 0) return;
|
|
15247
15712
|
const constructorFacts = readConstructor(
|
|
@@ -15275,8 +15740,120 @@ var require_port_for_service_default = createRule({
|
|
|
15275
15740
|
}
|
|
15276
15741
|
});
|
|
15277
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
|
+
|
|
15278
15855
|
// src/rules/require-static-next-matcher.ts
|
|
15279
|
-
import { AST_NODE_TYPES as
|
|
15856
|
+
import { AST_NODE_TYPES as AST_NODE_TYPES68 } from "@typescript-eslint/utils";
|
|
15280
15857
|
var REQUIRE_STATIC_NEXT_MATCHER_DOCUMENTATION = {
|
|
15281
15858
|
summary: "Require Next.js middleware and proxy matcher configuration to contain only build-time literals.",
|
|
15282
15859
|
rationale: "Next.js must statically analyze matcher values at build time; computed values are ignored.",
|
|
@@ -15289,34 +15866,34 @@ var REQUIRE_STATIC_NEXT_MATCHER_DOCUMENTATION = {
|
|
|
15289
15866
|
};
|
|
15290
15867
|
var NEXT_ENTRY_FILE = /(?:^|[/\\])(?:middleware|proxy)\.[cm]?[jt]sx?$/u;
|
|
15291
15868
|
function unwrapExpression3(node) {
|
|
15292
|
-
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) {
|
|
15293
15870
|
return unwrapExpression3(node.expression);
|
|
15294
15871
|
}
|
|
15295
15872
|
return node;
|
|
15296
15873
|
}
|
|
15297
15874
|
function isStaticValue(node) {
|
|
15298
15875
|
const value = unwrapExpression3(node);
|
|
15299
|
-
if (value.type ===
|
|
15876
|
+
if (value.type === AST_NODE_TYPES68.Literal) {
|
|
15300
15877
|
return true;
|
|
15301
15878
|
}
|
|
15302
|
-
if (value.type ===
|
|
15879
|
+
if (value.type === AST_NODE_TYPES68.TemplateLiteral) {
|
|
15303
15880
|
return value.expressions.length === 0;
|
|
15304
15881
|
}
|
|
15305
|
-
if (value.type ===
|
|
15882
|
+
if (value.type === AST_NODE_TYPES68.ArrayExpression) {
|
|
15306
15883
|
return value.elements.every(
|
|
15307
|
-
(element) => element !== null && element.type !==
|
|
15884
|
+
(element) => element !== null && element.type !== AST_NODE_TYPES68.SpreadElement && isStaticValue(element)
|
|
15308
15885
|
);
|
|
15309
15886
|
}
|
|
15310
|
-
if (value.type ===
|
|
15887
|
+
if (value.type === AST_NODE_TYPES68.ObjectExpression) {
|
|
15311
15888
|
return value.properties.every(
|
|
15312
|
-
(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)
|
|
15313
15890
|
);
|
|
15314
15891
|
}
|
|
15315
15892
|
return false;
|
|
15316
15893
|
}
|
|
15317
15894
|
function propertyName4(property) {
|
|
15318
15895
|
if (property.computed) return null;
|
|
15319
|
-
if (property.key.type ===
|
|
15896
|
+
if (property.key.type === AST_NODE_TYPES68.Identifier) return property.key.name;
|
|
15320
15897
|
return typeof property.key.value === "string" ? property.key.value : null;
|
|
15321
15898
|
}
|
|
15322
15899
|
var require_static_next_matcher_default = createRule({
|
|
@@ -15339,19 +15916,19 @@ var require_static_next_matcher_default = createRule({
|
|
|
15339
15916
|
}
|
|
15340
15917
|
return {
|
|
15341
15918
|
ExportNamedDeclaration(node) {
|
|
15342
|
-
if (node.declaration?.type !==
|
|
15919
|
+
if (node.declaration?.type !== AST_NODE_TYPES68.VariableDeclaration) {
|
|
15343
15920
|
return;
|
|
15344
15921
|
}
|
|
15345
15922
|
for (const declaration of node.declaration.declarations) {
|
|
15346
|
-
if (declaration.id.type !==
|
|
15923
|
+
if (declaration.id.type !== AST_NODE_TYPES68.Identifier || declaration.id.name !== "config" || declaration.init === null) {
|
|
15347
15924
|
continue;
|
|
15348
15925
|
}
|
|
15349
15926
|
const config = unwrapExpression3(declaration.init);
|
|
15350
|
-
if (config.type !==
|
|
15927
|
+
if (config.type !== AST_NODE_TYPES68.ObjectExpression) {
|
|
15351
15928
|
continue;
|
|
15352
15929
|
}
|
|
15353
15930
|
for (const property of config.properties) {
|
|
15354
|
-
if (property.type !==
|
|
15931
|
+
if (property.type !== AST_NODE_TYPES68.Property || propertyName4(property) !== "matcher" || property.value.type === AST_NODE_TYPES68.AssignmentPattern) {
|
|
15355
15932
|
continue;
|
|
15356
15933
|
}
|
|
15357
15934
|
if (!isStaticValue(property.value)) {
|
|
@@ -15365,7 +15942,7 @@ var require_static_next_matcher_default = createRule({
|
|
|
15365
15942
|
});
|
|
15366
15943
|
|
|
15367
15944
|
// src/rules/require-use-form-default-values.ts
|
|
15368
|
-
import { ASTUtils as
|
|
15945
|
+
import { ASTUtils as ASTUtils20 } from "@typescript-eslint/utils";
|
|
15369
15946
|
var REQUIRE_USE_FORM_DEFAULT_VALUES_DOCUMENTATION = {
|
|
15370
15947
|
summary: "react-hook-form useForm call without defaultValues",
|
|
15371
15948
|
rationale: "Without an explicit initial value, fields can change from uncontrolled to controlled as data arrives, reset behavior becomes ambiguous, and the form's initial shape no longer documents the values users can edit.",
|
|
@@ -15419,13 +15996,13 @@ var require_use_form_default_values_default = createRule({
|
|
|
15419
15996
|
if (node.source.value !== "react-hook-form") return;
|
|
15420
15997
|
for (const specifier of node.specifiers) {
|
|
15421
15998
|
if (specifier.type !== "ImportSpecifier" || (specifier.imported.type === "Identifier" ? specifier.imported.name : specifier.imported.value) !== "useForm") continue;
|
|
15422
|
-
const variable =
|
|
15999
|
+
const variable = ASTUtils20.findVariable(context.sourceCode.getScope(specifier.local), specifier.local.name);
|
|
15423
16000
|
if (variable) importedHooks.add(variable);
|
|
15424
16001
|
}
|
|
15425
16002
|
},
|
|
15426
16003
|
CallExpression(node) {
|
|
15427
16004
|
if (node.callee.type !== "Identifier") return;
|
|
15428
|
-
const variable =
|
|
16005
|
+
const variable = ASTUtils20.findVariable(context.sourceCode.getScope(node.callee), node.callee.name);
|
|
15429
16006
|
const options = node.arguments[0];
|
|
15430
16007
|
if (!variable || !importedHooks.has(variable) || options !== void 0 && options.type !== "ObjectExpression" || hasDefaultValues(options)) return;
|
|
15431
16008
|
context.report({ node, messageId: "requireUseFormDefaultValues" });
|
|
@@ -15502,8 +16079,8 @@ var require_use_server_in_actions_file_default = createRule({
|
|
|
15502
16079
|
|
|
15503
16080
|
// src/rules/require-zod-form-validation.ts
|
|
15504
16081
|
import {
|
|
15505
|
-
AST_NODE_TYPES as
|
|
15506
|
-
ASTUtils as
|
|
16082
|
+
AST_NODE_TYPES as AST_NODE_TYPES69,
|
|
16083
|
+
ASTUtils as ASTUtils21
|
|
15507
16084
|
} from "@typescript-eslint/utils";
|
|
15508
16085
|
var REQUIRE_ZOD_FORM_VALIDATION_DOCUMENTATION = {
|
|
15509
16086
|
summary: "Require Zod validation (`Schema.parse(...)` / `Schema.safeParse(...)`) when reading values out of a `FormData` object.",
|
|
@@ -15529,14 +16106,14 @@ var FORM_VALUE_METHODS = /* @__PURE__ */ new Set(["get", "getAll"]);
|
|
|
15529
16106
|
var zodReceiverRoot = (node) => {
|
|
15530
16107
|
let current = node;
|
|
15531
16108
|
while (true) {
|
|
15532
|
-
if (current.type ===
|
|
16109
|
+
if (current.type === AST_NODE_TYPES69.Identifier) {
|
|
15533
16110
|
return current;
|
|
15534
16111
|
}
|
|
15535
|
-
if (current.type ===
|
|
16112
|
+
if (current.type === AST_NODE_TYPES69.CallExpression) {
|
|
15536
16113
|
current = current.callee;
|
|
15537
16114
|
continue;
|
|
15538
16115
|
}
|
|
15539
|
-
if (current.type ===
|
|
16116
|
+
if (current.type === AST_NODE_TYPES69.MemberExpression) {
|
|
15540
16117
|
current = current.object;
|
|
15541
16118
|
continue;
|
|
15542
16119
|
}
|
|
@@ -15545,12 +16122,12 @@ var zodReceiverRoot = (node) => {
|
|
|
15545
16122
|
};
|
|
15546
16123
|
var isFormDataMethodCall = (node) => {
|
|
15547
16124
|
let current = node;
|
|
15548
|
-
if (current.type ===
|
|
16125
|
+
if (current.type === AST_NODE_TYPES69.AwaitExpression) {
|
|
15549
16126
|
current = current.argument;
|
|
15550
16127
|
}
|
|
15551
|
-
if (current.type !==
|
|
16128
|
+
if (current.type !== AST_NODE_TYPES69.CallExpression) return false;
|
|
15552
16129
|
const callee = current.callee;
|
|
15553
|
-
return callee.type ===
|
|
16130
|
+
return callee.type === AST_NODE_TYPES69.MemberExpression && !callee.computed && callee.property.type === AST_NODE_TYPES69.Identifier && callee.property.name === "formData";
|
|
15554
16131
|
};
|
|
15555
16132
|
var require_zod_form_validation_default = createRule({
|
|
15556
16133
|
name: "require-zod-form-validation",
|
|
@@ -15571,7 +16148,7 @@ var require_zod_form_validation_default = createRule({
|
|
|
15571
16148
|
return {};
|
|
15572
16149
|
}
|
|
15573
16150
|
const zodBindings = /* @__PURE__ */ new Set();
|
|
15574
|
-
const resolvedBinding = (identifier) =>
|
|
16151
|
+
const resolvedBinding = (identifier) => ASTUtils21.findVariable(
|
|
15575
16152
|
context.sourceCode.getScope(identifier),
|
|
15576
16153
|
identifier.name
|
|
15577
16154
|
);
|
|
@@ -15581,16 +16158,16 @@ var require_zod_form_validation_default = createRule({
|
|
|
15581
16158
|
return false;
|
|
15582
16159
|
}
|
|
15583
16160
|
const definition = binding.defs[0];
|
|
15584
|
-
if (definition?.type !== "Variable" || definition.node.type !==
|
|
16161
|
+
if (definition?.type !== "Variable" || definition.node.type !== AST_NODE_TYPES69.VariableDeclarator) {
|
|
15585
16162
|
return false;
|
|
15586
16163
|
}
|
|
15587
16164
|
const init = definition.node.init;
|
|
15588
|
-
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;
|
|
15589
16166
|
};
|
|
15590
16167
|
const isZodParseCall = (node) => {
|
|
15591
|
-
if (node.type !==
|
|
16168
|
+
if (node.type !== AST_NODE_TYPES69.CallExpression) return false;
|
|
15592
16169
|
const callee = node.callee;
|
|
15593
|
-
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)) {
|
|
15594
16171
|
return false;
|
|
15595
16172
|
}
|
|
15596
16173
|
const root = zodReceiverRoot(callee.object);
|
|
@@ -15599,14 +16176,14 @@ var require_zod_form_validation_default = createRule({
|
|
|
15599
16176
|
return binding !== null && zodBindings.has(binding) || (root.name === "z" || ZOD_SCHEMA_NAME_RE.test(root.name)) && !isProvablyNonZodLocal(root);
|
|
15600
16177
|
};
|
|
15601
16178
|
const isFormSourceIdentifier = (node) => {
|
|
15602
|
-
if (node.type !==
|
|
16179
|
+
if (node.type !== AST_NODE_TYPES69.Identifier) return false;
|
|
15603
16180
|
const conventionalName = /formdata/i.test(node.name);
|
|
15604
16181
|
let scope = context.sourceCode.getScope(node);
|
|
15605
16182
|
while (scope !== null) {
|
|
15606
16183
|
const variable = scope.set.get(node.name);
|
|
15607
16184
|
if (variable !== void 0 && variable.defs.length === 1) {
|
|
15608
16185
|
const def = variable.defs[0];
|
|
15609
|
-
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) {
|
|
15610
16187
|
return isFormDataMethodCall(def.node.init);
|
|
15611
16188
|
}
|
|
15612
16189
|
return def?.type === "Parameter" && conventionalName;
|
|
@@ -15617,8 +16194,8 @@ var require_zod_form_validation_default = createRule({
|
|
|
15617
16194
|
};
|
|
15618
16195
|
const isFormDataGetCall = (node) => {
|
|
15619
16196
|
const callee = node.callee;
|
|
15620
|
-
if (callee.type !==
|
|
15621
|
-
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)) {
|
|
15622
16199
|
return false;
|
|
15623
16200
|
}
|
|
15624
16201
|
return isFormSourceIdentifier(callee.object);
|
|
@@ -15634,16 +16211,16 @@ var require_zod_form_validation_default = createRule({
|
|
|
15634
16211
|
const hasZodParseAncestor = (node) => zodParseAncestor(node) !== null;
|
|
15635
16212
|
const isInstanceofNarrowing = (node) => {
|
|
15636
16213
|
const parent = node.parent;
|
|
15637
|
-
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");
|
|
15638
16215
|
};
|
|
15639
16216
|
const boundDeclarator = (node) => {
|
|
15640
16217
|
let current = node;
|
|
15641
16218
|
let parent = current.parent;
|
|
15642
|
-
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) {
|
|
15643
16220
|
current = parent;
|
|
15644
16221
|
parent = current.parent;
|
|
15645
16222
|
}
|
|
15646
|
-
if (parent.type ===
|
|
16223
|
+
if (parent.type === AST_NODE_TYPES69.VariableDeclarator && parent.init === current && parent.id.type === AST_NODE_TYPES69.Identifier) {
|
|
15647
16224
|
return parent;
|
|
15648
16225
|
}
|
|
15649
16226
|
return null;
|
|
@@ -15652,7 +16229,7 @@ var require_zod_form_validation_default = createRule({
|
|
|
15652
16229
|
let current = node;
|
|
15653
16230
|
while (current.parent !== void 0) {
|
|
15654
16231
|
const parent = current.parent;
|
|
15655
|
-
if (parent.type ===
|
|
16232
|
+
if (parent.type === AST_NODE_TYPES69.BlockStatement || parent.type === AST_NODE_TYPES69.Program) {
|
|
15656
16233
|
return current;
|
|
15657
16234
|
}
|
|
15658
16235
|
current = parent;
|
|
@@ -15661,12 +16238,12 @@ var require_zod_form_validation_default = createRule({
|
|
|
15661
16238
|
};
|
|
15662
16239
|
const zodParseMethod = (call) => {
|
|
15663
16240
|
const callee = call.callee;
|
|
15664
|
-
return callee.type ===
|
|
16241
|
+
return callee.type === AST_NODE_TYPES69.MemberExpression && !callee.computed && callee.property.type === AST_NODE_TYPES69.Identifier ? callee.property.name : null;
|
|
15665
16242
|
};
|
|
15666
16243
|
const hasConditionalAncestorBeforeStatement = (node, statement) => {
|
|
15667
16244
|
let current = node.parent;
|
|
15668
16245
|
while (current !== void 0 && current !== statement) {
|
|
15669
|
-
if (current.type ===
|
|
16246
|
+
if (current.type === AST_NODE_TYPES69.LogicalExpression || current.type === AST_NODE_TYPES69.ConditionalExpression) {
|
|
15670
16247
|
return true;
|
|
15671
16248
|
}
|
|
15672
16249
|
current = current.parent;
|
|
@@ -15676,7 +16253,7 @@ var require_zod_form_validation_default = createRule({
|
|
|
15676
16253
|
const isAwaitedBeforeStatement = (node, statement) => {
|
|
15677
16254
|
let current = node.parent;
|
|
15678
16255
|
while (current !== void 0 && current !== statement) {
|
|
15679
|
-
if (current.type ===
|
|
16256
|
+
if (current.type === AST_NODE_TYPES69.AwaitExpression) return true;
|
|
15680
16257
|
current = current.parent;
|
|
15681
16258
|
}
|
|
15682
16259
|
return false;
|
|
@@ -15689,7 +16266,7 @@ var require_zod_form_validation_default = createRule({
|
|
|
15689
16266
|
if (declarationStatement === null || validationStatement === null || declarationStatement.parent !== validationStatement.parent || validationStatement.range[0] <= declarationStatement.range[1] || hasConditionalAncestorBeforeStatement(parse2, validationStatement)) {
|
|
15690
16267
|
return null;
|
|
15691
16268
|
}
|
|
15692
|
-
if (validationStatement.type !==
|
|
16269
|
+
if (validationStatement.type !== AST_NODE_TYPES69.VariableDeclaration && validationStatement.type !== AST_NODE_TYPES69.ExpressionStatement) {
|
|
15693
16270
|
return null;
|
|
15694
16271
|
}
|
|
15695
16272
|
const method = zodParseMethod(parse2);
|
|
@@ -15701,16 +16278,16 @@ var require_zod_form_validation_default = createRule({
|
|
|
15701
16278
|
};
|
|
15702
16279
|
const isSafePrevalidationInspection = (identifier) => {
|
|
15703
16280
|
const parent = identifier.parent;
|
|
15704
|
-
if (parent.type ===
|
|
16281
|
+
if (parent.type === AST_NODE_TYPES69.UnaryExpression && parent.operator === "typeof") {
|
|
15705
16282
|
return true;
|
|
15706
16283
|
}
|
|
15707
|
-
if (parent.type !==
|
|
16284
|
+
if (parent.type !== AST_NODE_TYPES69.BinaryExpression || parent.left !== identifier) {
|
|
15708
16285
|
return false;
|
|
15709
16286
|
}
|
|
15710
16287
|
if (parent.operator === "instanceof") {
|
|
15711
|
-
return parent.right.type ===
|
|
16288
|
+
return parent.right.type === AST_NODE_TYPES69.Identifier && (parent.right.name === "File" || parent.right.name === "Blob");
|
|
15712
16289
|
}
|
|
15713
|
-
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");
|
|
15714
16291
|
};
|
|
15715
16292
|
const isDescendantOf = (node, ancestor) => {
|
|
15716
16293
|
let current = node;
|
|
@@ -15721,23 +16298,23 @@ var require_zod_form_validation_default = createRule({
|
|
|
15721
16298
|
return false;
|
|
15722
16299
|
};
|
|
15723
16300
|
const blockTerminates = (node) => {
|
|
15724
|
-
if (node.type ===
|
|
16301
|
+
if (node.type === AST_NODE_TYPES69.ReturnStatement || node.type === AST_NODE_TYPES69.ThrowStatement) {
|
|
15725
16302
|
return true;
|
|
15726
16303
|
}
|
|
15727
|
-
if (node.type !==
|
|
16304
|
+
if (node.type !== AST_NODE_TYPES69.BlockStatement || node.body.length === 0) return false;
|
|
15728
16305
|
const last = node.body.at(-1);
|
|
15729
16306
|
return last !== void 0 && blockTerminates(last);
|
|
15730
16307
|
};
|
|
15731
16308
|
const narrowingIf = (identifier) => {
|
|
15732
16309
|
const comparison = identifier.parent;
|
|
15733
|
-
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") {
|
|
15734
16311
|
return null;
|
|
15735
16312
|
}
|
|
15736
16313
|
const maybeNegation = comparison.parent;
|
|
15737
|
-
const negated = maybeNegation?.type ===
|
|
16314
|
+
const negated = maybeNegation?.type === AST_NODE_TYPES69.UnaryExpression && maybeNegation.operator === "!";
|
|
15738
16315
|
const test = negated ? maybeNegation : comparison;
|
|
15739
16316
|
const branch = test.parent;
|
|
15740
|
-
return branch?.type ===
|
|
16317
|
+
return branch?.type === AST_NODE_TYPES69.IfStatement && branch.test === test ? { branch, positive: !negated } : null;
|
|
15741
16318
|
};
|
|
15742
16319
|
const useDominatedByNarrowing = (use, narrowings) => narrowings.some(({ branch, positive }) => {
|
|
15743
16320
|
if (positive) return isDescendantOf(use, branch.consequent);
|
|
@@ -15757,7 +16334,7 @@ var require_zod_form_validation_default = createRule({
|
|
|
15757
16334
|
const variable = context.sourceCode.getDeclaredVariables(declarator)[0];
|
|
15758
16335
|
if (variable === void 0) return false;
|
|
15759
16336
|
const references = variable.references.filter((reference) => !reference.isWriteOnly()).map((reference) => reference.identifier).filter(
|
|
15760
|
-
(identifier) => identifier.type ===
|
|
16337
|
+
(identifier) => identifier.type === AST_NODE_TYPES69.Identifier
|
|
15761
16338
|
);
|
|
15762
16339
|
if (references.length === 0) return false;
|
|
15763
16340
|
const narrowings = references.map(narrowingIf).filter(
|
|
@@ -15783,7 +16360,7 @@ var require_zod_form_validation_default = createRule({
|
|
|
15783
16360
|
ImportDeclaration(node) {
|
|
15784
16361
|
if (!isZodModule(node.source.value)) return;
|
|
15785
16362
|
for (const specifier of node.specifiers) {
|
|
15786
|
-
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")) {
|
|
15787
16364
|
const binding = resolvedBinding(specifier.local);
|
|
15788
16365
|
if (binding !== null) zodBindings.add(binding);
|
|
15789
16366
|
}
|
|
@@ -15868,7 +16445,7 @@ var store_insert_requires_on_conflict_default = createRule({
|
|
|
15868
16445
|
});
|
|
15869
16446
|
|
|
15870
16447
|
// src/rules/stepdown.ts
|
|
15871
|
-
import { AST_NODE_TYPES as
|
|
16448
|
+
import { AST_NODE_TYPES as AST_NODE_TYPES70, ASTUtils as ASTUtils22 } from "@typescript-eslint/utils";
|
|
15872
16449
|
var STEPDOWN_DOCUMENTATION = {
|
|
15873
16450
|
summary: "Place a private helper below its sole direct same-scope caller.",
|
|
15874
16451
|
rationale: "Caller-first ordering lets a reader follow the main flow before descending into implementation details.",
|
|
@@ -15888,7 +16465,7 @@ var STEPDOWN_DOCUMENTATION = {
|
|
|
15888
16465
|
]
|
|
15889
16466
|
};
|
|
15890
16467
|
function isFunction(node) {
|
|
15891
|
-
return node.type ===
|
|
16468
|
+
return node.type === AST_NODE_TYPES70.ArrowFunctionExpression || node.type === AST_NODE_TYPES70.FunctionDeclaration || node.type === AST_NODE_TYPES70.FunctionExpression;
|
|
15892
16469
|
}
|
|
15893
16470
|
function reportMisordered(context, candidates, scopeDefinitions, calls, pinned, canMove = () => true, makeFix) {
|
|
15894
16471
|
const byName = new Map(scopeDefinitions.map((definition) => [definition.name, definition]));
|
|
@@ -15985,8 +16562,8 @@ function moduleScope(context, program) {
|
|
|
15985
16562
|
for (const node of declarations) counts.set(node.name, (counts.get(node.name) ?? 0) + 1);
|
|
15986
16563
|
const overloadNames = new Set(
|
|
15987
16564
|
program.body.flatMap((statement) => {
|
|
15988
|
-
const node = statement.type ===
|
|
15989
|
-
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] : [];
|
|
15990
16567
|
})
|
|
15991
16568
|
);
|
|
15992
16569
|
const exported = exportedNames(program);
|
|
@@ -16010,7 +16587,7 @@ function moduleScope(context, program) {
|
|
|
16010
16587
|
const nearestFunction2 = [...ancestors].reverse().find(isFunction);
|
|
16011
16588
|
const parent = identifier.parent;
|
|
16012
16589
|
const callerDefinition = nearestFunction2 === void 0 ? void 0 : byFunction.get(nearestFunction2);
|
|
16013
|
-
if (callerDefinition === void 0 || parent.type !==
|
|
16590
|
+
if (callerDefinition === void 0 || parent.type !== AST_NODE_TYPES70.CallExpression || parent.callee !== identifier) {
|
|
16014
16591
|
pinned.add(definition.name);
|
|
16015
16592
|
continue;
|
|
16016
16593
|
}
|
|
@@ -16025,38 +16602,38 @@ function moduleScope(context, program) {
|
|
|
16025
16602
|
function exportedNames(program) {
|
|
16026
16603
|
const names = /* @__PURE__ */ new Set();
|
|
16027
16604
|
for (const statement of program.body) {
|
|
16028
|
-
if (statement.type !==
|
|
16029
|
-
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) {
|
|
16030
16607
|
names.add(statement.declaration.id.name);
|
|
16031
16608
|
}
|
|
16032
|
-
if (statement.declaration?.type ===
|
|
16609
|
+
if (statement.declaration?.type === AST_NODE_TYPES70.VariableDeclaration) {
|
|
16033
16610
|
for (const declarator of statement.declaration.declarations) {
|
|
16034
|
-
if (declarator.id.type ===
|
|
16611
|
+
if (declarator.id.type === AST_NODE_TYPES70.Identifier) names.add(declarator.id.name);
|
|
16035
16612
|
}
|
|
16036
16613
|
}
|
|
16037
16614
|
for (const specifier of statement.specifiers) {
|
|
16038
|
-
if (specifier.exportKind !== "type" && specifier.local.type ===
|
|
16615
|
+
if (specifier.exportKind !== "type" && specifier.local.type === AST_NODE_TYPES70.Identifier) {
|
|
16039
16616
|
names.add(specifier.local.name);
|
|
16040
16617
|
}
|
|
16041
16618
|
}
|
|
16042
16619
|
}
|
|
16043
16620
|
for (const statement of program.body) {
|
|
16044
|
-
if (statement.type ===
|
|
16045
|
-
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);
|
|
16046
16623
|
}
|
|
16047
16624
|
return names;
|
|
16048
16625
|
}
|
|
16049
16626
|
function moduleDefinitions(program) {
|
|
16050
16627
|
const definitions = [];
|
|
16051
16628
|
for (const statement of program.body) {
|
|
16052
|
-
const node = statement.type ===
|
|
16053
|
-
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) {
|
|
16054
16631
|
definitions.push({ name: node.id.name, node, functionNode: node, bindingNode: node });
|
|
16055
16632
|
continue;
|
|
16056
16633
|
}
|
|
16057
|
-
if (node?.type !==
|
|
16634
|
+
if (node?.type !== AST_NODE_TYPES70.VariableDeclaration || node.kind !== "const") continue;
|
|
16058
16635
|
for (const declarator of node.declarations) {
|
|
16059
|
-
if (declarator.id.type ===
|
|
16636
|
+
if (declarator.id.type === AST_NODE_TYPES70.Identifier && declarator.init !== null && isFunction(declarator.init)) {
|
|
16060
16637
|
definitions.push({
|
|
16061
16638
|
name: declarator.id.name,
|
|
16062
16639
|
node: declarator,
|
|
@@ -16069,21 +16646,21 @@ function moduleDefinitions(program) {
|
|
|
16069
16646
|
return definitions;
|
|
16070
16647
|
}
|
|
16071
16648
|
function methodName(node) {
|
|
16072
|
-
if (node.key.type ===
|
|
16073
|
-
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;
|
|
16074
16651
|
}
|
|
16075
16652
|
function referencedMethod(context, node, classVariables) {
|
|
16076
|
-
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;
|
|
16077
16654
|
const isClassReference = objectVariable !== null && classVariables.has(objectVariable);
|
|
16078
|
-
if (node.object.type !==
|
|
16079
|
-
if (node.property.type ===
|
|
16080
|
-
if (!node.computed && node.property.type ===
|
|
16081
|
-
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;
|
|
16082
16659
|
}
|
|
16083
16660
|
function referencedPropertyName(node) {
|
|
16084
|
-
if (node.property.type ===
|
|
16085
|
-
if (!node.computed && node.property.type ===
|
|
16086
|
-
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;
|
|
16087
16664
|
}
|
|
16088
16665
|
function walk2(node, visitorKeys, visit, nestedFunction = false) {
|
|
16089
16666
|
visit(node, nestedFunction);
|
|
@@ -16099,7 +16676,7 @@ function walk2(node, visitorKeys, visit, nestedFunction = false) {
|
|
|
16099
16676
|
}
|
|
16100
16677
|
function classScope(context, node, computedReferenceNames) {
|
|
16101
16678
|
const methods = node.body.body.filter(
|
|
16102
|
-
(member) => member.type ===
|
|
16679
|
+
(member) => member.type === AST_NODE_TYPES70.MethodDefinition
|
|
16103
16680
|
);
|
|
16104
16681
|
const counts = /* @__PURE__ */ new Map();
|
|
16105
16682
|
for (const method of methods) {
|
|
@@ -16107,8 +16684,8 @@ function classScope(context, node, computedReferenceNames) {
|
|
|
16107
16684
|
if (name !== null) counts.set(name, (counts.get(name) ?? 0) + 1);
|
|
16108
16685
|
}
|
|
16109
16686
|
for (const member of node.body.body) {
|
|
16110
|
-
if (member.type !==
|
|
16111
|
-
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;
|
|
16112
16689
|
if (name !== null) counts.set(name, (counts.get(name) ?? 0) + 1);
|
|
16113
16690
|
}
|
|
16114
16691
|
const scopeDefinitions = methods.flatMap((method) => {
|
|
@@ -16117,7 +16694,7 @@ function classScope(context, node, computedReferenceNames) {
|
|
|
16117
16694
|
});
|
|
16118
16695
|
const definitions = methods.flatMap((method) => {
|
|
16119
16696
|
const name = methodName(method);
|
|
16120
|
-
const isPrivate = method.accessibility === "private" || method.key.type ===
|
|
16697
|
+
const isPrivate = method.accessibility === "private" || method.key.type === AST_NODE_TYPES70.PrivateIdentifier;
|
|
16121
16698
|
return name !== null && isPrivate && counts.get(name) === 1 && method.decorators.length === 0 ? [{ name, node: method }] : [];
|
|
16122
16699
|
});
|
|
16123
16700
|
if (definitions.length === 0) return;
|
|
@@ -16126,11 +16703,11 @@ function classScope(context, node, computedReferenceNames) {
|
|
|
16126
16703
|
const pinned = /* @__PURE__ */ new Set();
|
|
16127
16704
|
const classVariables = /* @__PURE__ */ new Set();
|
|
16128
16705
|
if (node.id !== null) {
|
|
16129
|
-
const internal =
|
|
16706
|
+
const internal = ASTUtils22.findVariable(context.sourceCode.getScope(node), node.id.name);
|
|
16130
16707
|
if (internal !== null) classVariables.add(internal);
|
|
16131
16708
|
}
|
|
16132
|
-
if (node.type ===
|
|
16133
|
-
const outer =
|
|
16709
|
+
if (node.type === AST_NODE_TYPES70.ClassExpression && node.parent.type === AST_NODE_TYPES70.VariableDeclarator && node.parent.id.type === AST_NODE_TYPES70.Identifier) {
|
|
16710
|
+
const outer = ASTUtils22.findVariable(context.sourceCode.getScope(node.parent), node.parent.id.name);
|
|
16134
16711
|
if (outer !== null) classVariables.add(outer);
|
|
16135
16712
|
}
|
|
16136
16713
|
for (const method of methods) {
|
|
@@ -16146,27 +16723,27 @@ function classScope(context, node, computedReferenceNames) {
|
|
|
16146
16723
|
}
|
|
16147
16724
|
const thisValue = (value) => {
|
|
16148
16725
|
let current = value;
|
|
16149
|
-
while (current?.type ===
|
|
16150
|
-
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;
|
|
16151
16728
|
};
|
|
16152
16729
|
const collectAlias = (current, nestedFunction) => {
|
|
16153
|
-
if (nestedFunction || current.type !==
|
|
16154
|
-
if (current.type ===
|
|
16155
|
-
const binding = current.type ===
|
|
16156
|
-
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;
|
|
16157
16734
|
if (!thisValue(value)) return;
|
|
16158
|
-
if (binding.type ===
|
|
16735
|
+
if (binding.type === AST_NODE_TYPES70.ObjectPattern) {
|
|
16159
16736
|
for (const property of binding.properties) {
|
|
16160
|
-
if (property.type ===
|
|
16737
|
+
if (property.type === AST_NODE_TYPES70.RestElement) {
|
|
16161
16738
|
for (const name of privateNames) pinned.add(name);
|
|
16162
|
-
} else if (property.key.type ===
|
|
16739
|
+
} else if (property.key.type === AST_NODE_TYPES70.Identifier && privateNames.has(property.key.name)) {
|
|
16163
16740
|
pinned.add(property.key.name);
|
|
16164
16741
|
}
|
|
16165
16742
|
}
|
|
16166
16743
|
return;
|
|
16167
16744
|
}
|
|
16168
|
-
if (binding.type !==
|
|
16169
|
-
const variable =
|
|
16745
|
+
if (binding.type !== AST_NODE_TYPES70.Identifier) return;
|
|
16746
|
+
const variable = ASTUtils22.findVariable(context.sourceCode.getScope(binding), binding.name);
|
|
16170
16747
|
if (variable !== null) {
|
|
16171
16748
|
methodClassVariables.add(variable);
|
|
16172
16749
|
methodAliases.add(variable);
|
|
@@ -16179,16 +16756,16 @@ function classScope(context, node, computedReferenceNames) {
|
|
|
16179
16756
|
walk2(statement, context.sourceCode.visitorKeys, collectAlias);
|
|
16180
16757
|
}
|
|
16181
16758
|
const visitCall = (current, nestedFunction) => {
|
|
16182
|
-
if (current.type ===
|
|
16759
|
+
if (current.type === AST_NODE_TYPES70.VariableDeclarator && current.id.type === AST_NODE_TYPES70.ObjectPattern && thisValue(current.init)) {
|
|
16183
16760
|
for (const property of current.id.properties) {
|
|
16184
|
-
if (property.type ===
|
|
16761
|
+
if (property.type === AST_NODE_TYPES70.RestElement) {
|
|
16185
16762
|
for (const name of privateNames) pinned.add(name);
|
|
16186
16763
|
continue;
|
|
16187
16764
|
}
|
|
16188
|
-
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);
|
|
16189
16766
|
}
|
|
16190
16767
|
}
|
|
16191
|
-
if (current.type !==
|
|
16768
|
+
if (current.type !== AST_NODE_TYPES70.MemberExpression) return;
|
|
16192
16769
|
const target = referencedMethod(context, current, methodClassVariables);
|
|
16193
16770
|
if (target === null) {
|
|
16194
16771
|
const possibleTarget = referencedPropertyName(current);
|
|
@@ -16196,12 +16773,12 @@ function classScope(context, node, computedReferenceNames) {
|
|
|
16196
16773
|
return;
|
|
16197
16774
|
}
|
|
16198
16775
|
if (!privateNames.has(target)) return;
|
|
16199
|
-
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;
|
|
16200
16777
|
if (objectVariable !== null && methodAliases.has(objectVariable)) {
|
|
16201
16778
|
pinned.add(target);
|
|
16202
16779
|
return;
|
|
16203
16780
|
}
|
|
16204
|
-
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) {
|
|
16205
16782
|
pinned.add(target);
|
|
16206
16783
|
return;
|
|
16207
16784
|
}
|
|
@@ -16221,9 +16798,9 @@ function classScope(context, node, computedReferenceNames) {
|
|
|
16221
16798
|
}
|
|
16222
16799
|
}
|
|
16223
16800
|
for (const member of node.body.body) {
|
|
16224
|
-
if (member.type ===
|
|
16801
|
+
if (member.type === AST_NODE_TYPES70.MethodDefinition || member.type === AST_NODE_TYPES70.TSAbstractMethodDefinition) continue;
|
|
16225
16802
|
walk2(member, context.sourceCode.visitorKeys, (current) => {
|
|
16226
|
-
if (current.type !==
|
|
16803
|
+
if (current.type !== AST_NODE_TYPES70.MemberExpression) return;
|
|
16227
16804
|
const target = referencedMethod(context, current, classVariables);
|
|
16228
16805
|
const possibleTarget = target ?? referencedPropertyName(current);
|
|
16229
16806
|
if (possibleTarget !== null && privateNames.has(possibleTarget)) pinned.add(possibleTarget);
|
|
@@ -16275,12 +16852,12 @@ function classScope(context, node, computedReferenceNames) {
|
|
|
16275
16852
|
}
|
|
16276
16853
|
function isClassRuntimeBarrier(member) {
|
|
16277
16854
|
switch (member.type) {
|
|
16278
|
-
case
|
|
16855
|
+
case AST_NODE_TYPES70.StaticBlock:
|
|
16279
16856
|
return true;
|
|
16280
|
-
case
|
|
16281
|
-
case
|
|
16857
|
+
case AST_NODE_TYPES70.PropertyDefinition:
|
|
16858
|
+
case AST_NODE_TYPES70.AccessorProperty:
|
|
16282
16859
|
return member.static || member.computed || member.decorators.length > 0 || member.value !== null;
|
|
16283
|
-
case
|
|
16860
|
+
case AST_NODE_TYPES70.MethodDefinition:
|
|
16284
16861
|
return member.computed || member.decorators.length > 0;
|
|
16285
16862
|
default:
|
|
16286
16863
|
return false;
|
|
@@ -16313,7 +16890,7 @@ var stepdown_default = createRule({
|
|
|
16313
16890
|
moduleScope(context, program);
|
|
16314
16891
|
const computedReferenceNames = /* @__PURE__ */ new Set();
|
|
16315
16892
|
walk2(program, context.sourceCode.visitorKeys, (node) => {
|
|
16316
|
-
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);
|
|
16317
16894
|
});
|
|
16318
16895
|
for (const node of classes) classScope(context, node, computedReferenceNames);
|
|
16319
16896
|
}
|
|
@@ -16322,7 +16899,7 @@ var stepdown_default = createRule({
|
|
|
16322
16899
|
});
|
|
16323
16900
|
|
|
16324
16901
|
// src/rules/source-coupled-test.ts
|
|
16325
|
-
import { AST_NODE_TYPES as
|
|
16902
|
+
import { AST_NODE_TYPES as AST_NODE_TYPES71 } from "@typescript-eslint/utils";
|
|
16326
16903
|
var GENERAL_SOURCE_SUFFIX_RE = /\.(?:bash|sh|ya?ml|jsonc|py|[cm]?[jt]s)$/iu;
|
|
16327
16904
|
var FS_MODULES = /* @__PURE__ */ new Set(["fs", "node:fs", "fs/promises", "node:fs/promises"]);
|
|
16328
16905
|
var FS_READERS = /* @__PURE__ */ new Set(["readFile", "readFileSync"]);
|
|
@@ -16391,28 +16968,28 @@ var SOURCE_COUPLED_TEST_DOCUMENTATION = {
|
|
|
16391
16968
|
]
|
|
16392
16969
|
};
|
|
16393
16970
|
function staticMemberName7(node) {
|
|
16394
|
-
if (!node.computed && node.property.type ===
|
|
16395
|
-
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;
|
|
16396
16973
|
return null;
|
|
16397
16974
|
}
|
|
16398
|
-
function
|
|
16399
|
-
if (node.type ===
|
|
16400
|
-
if (node.type ===
|
|
16401
|
-
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);
|
|
16402
16979
|
return node;
|
|
16403
16980
|
}
|
|
16404
16981
|
function stringValue(node) {
|
|
16405
|
-
const current =
|
|
16406
|
-
if (current.type ===
|
|
16407
|
-
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;
|
|
16408
16985
|
return null;
|
|
16409
16986
|
}
|
|
16410
16987
|
function importSource(node) {
|
|
16411
16988
|
return typeof node.source.value === "string" ? node.source.value : null;
|
|
16412
16989
|
}
|
|
16413
16990
|
function requireSource(node) {
|
|
16414
|
-
const current =
|
|
16415
|
-
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;
|
|
16416
16993
|
return stringValue(current.arguments[0]);
|
|
16417
16994
|
}
|
|
16418
16995
|
function newScope() {
|
|
@@ -16449,80 +17026,80 @@ function createSourceCoupledRule(name, documentation, sourceSuffixRe) {
|
|
|
16449
17026
|
return /* @__PURE__ */ new Set();
|
|
16450
17027
|
};
|
|
16451
17028
|
const sourcePath = (node) => {
|
|
16452
|
-
const current =
|
|
17029
|
+
const current = unwrap6(node);
|
|
16453
17030
|
const value = stringValue(current);
|
|
16454
17031
|
if (value !== null) return sourceSuffixRe.test(value);
|
|
16455
|
-
if (current.type ===
|
|
16456
|
-
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 === "+") {
|
|
16457
17034
|
return sourcePath(current.left) || sourcePath(current.right);
|
|
16458
17035
|
}
|
|
16459
|
-
if (current.type ===
|
|
16460
|
-
if (current.type ===
|
|
16461
|
-
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));
|
|
16462
17039
|
}
|
|
16463
|
-
if (current.type ===
|
|
17040
|
+
if (current.type === AST_NODE_TYPES71.MemberExpression) return sourcePath(current.object);
|
|
16464
17041
|
return false;
|
|
16465
17042
|
};
|
|
16466
17043
|
const rawRead = (node) => {
|
|
16467
|
-
const current =
|
|
16468
|
-
if (current.type !==
|
|
16469
|
-
const callee =
|
|
16470
|
-
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) {
|
|
16471
17048
|
return visible("fsReaders", callee.name) && sourcePath(current.arguments[0]);
|
|
16472
17049
|
}
|
|
16473
|
-
if (callee.type !==
|
|
17050
|
+
if (callee.type !== AST_NODE_TYPES71.MemberExpression) return false;
|
|
16474
17051
|
const name2 = staticMemberName7(callee);
|
|
16475
|
-
const object =
|
|
16476
|
-
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]);
|
|
16477
17054
|
};
|
|
16478
17055
|
const rawOrigins = (node) => {
|
|
16479
|
-
const current =
|
|
16480
|
-
if (current.type ===
|
|
17056
|
+
const current = unwrap6(node);
|
|
17057
|
+
if (current.type === AST_NODE_TYPES71.Identifier) return visibleRawOrigins(current.name);
|
|
16481
17058
|
if (rawRead(current)) return /* @__PURE__ */ new Set([`${current.range[0]}:${current.range[1]}`]);
|
|
16482
|
-
if (current.type ===
|
|
16483
|
-
if (current.type ===
|
|
16484
|
-
if (current.type !==
|
|
16485
|
-
const callee =
|
|
16486
|
-
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();
|
|
16487
17064
|
const name2 = staticMemberName7(callee);
|
|
16488
17065
|
return name2 !== null && TEXT_TRANSFORMS.has(name2) ? rawOrigins(callee.object) : /* @__PURE__ */ new Set();
|
|
16489
17066
|
};
|
|
16490
17067
|
const evidenceOrigins = (node) => {
|
|
16491
|
-
const current =
|
|
17068
|
+
const current = unwrap6(node);
|
|
16492
17069
|
const direct = rawOrigins(current);
|
|
16493
17070
|
if (direct.size > 0) return direct;
|
|
16494
|
-
if (current.type ===
|
|
16495
|
-
if (current.type ===
|
|
16496
|
-
if (current.type !==
|
|
16497
|
-
const callee =
|
|
16498
|
-
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();
|
|
16499
17076
|
const name2 = staticMemberName7(callee);
|
|
16500
17077
|
if (name2 !== null && TEXT_PREDICATES.has(name2)) return rawOrigins(callee.object);
|
|
16501
|
-
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)]));
|
|
16502
17079
|
return /* @__PURE__ */ new Set();
|
|
16503
17080
|
};
|
|
16504
17081
|
const rawAssertionOrigins = (node) => {
|
|
16505
|
-
const callee =
|
|
16506
|
-
if (callee.type ===
|
|
16507
|
-
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)]));
|
|
16508
17085
|
}
|
|
16509
|
-
if (callee.type !==
|
|
17086
|
+
if (callee.type !== AST_NODE_TYPES71.MemberExpression) return /* @__PURE__ */ new Set();
|
|
16510
17087
|
const matcher = staticMemberName7(callee);
|
|
16511
17088
|
if (matcher === null) return /* @__PURE__ */ new Set();
|
|
16512
|
-
let receiver =
|
|
16513
|
-
while (receiver.type ===
|
|
16514
|
-
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") {
|
|
16515
17092
|
if (!EXPECT_MATCHERS.has(matcher)) return /* @__PURE__ */ new Set();
|
|
16516
|
-
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)]));
|
|
16517
17094
|
}
|
|
16518
|
-
if (receiver.type !==
|
|
16519
|
-
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)]));
|
|
16520
17097
|
};
|
|
16521
17098
|
const rawRegexExtractionOrigins = (node) => {
|
|
16522
|
-
const callee =
|
|
16523
|
-
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();
|
|
16524
17101
|
const argument = node.arguments[0];
|
|
16525
|
-
if (argument?.type !==
|
|
17102
|
+
if (argument?.type !== AST_NODE_TYPES71.Literal || !(argument.value instanceof RegExp)) return /* @__PURE__ */ new Set();
|
|
16526
17103
|
return rawOrigins(callee.object);
|
|
16527
17104
|
};
|
|
16528
17105
|
const declare = (name2, state) => {
|
|
@@ -16542,16 +17119,16 @@ function createSourceCoupledRule(name, documentation, sourceSuffixRe) {
|
|
|
16542
17119
|
}
|
|
16543
17120
|
};
|
|
16544
17121
|
const sourceCollection = (node) => {
|
|
16545
|
-
const current =
|
|
16546
|
-
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));
|
|
16547
17124
|
};
|
|
16548
17125
|
const declaredNames2 = (node) => {
|
|
16549
|
-
const current =
|
|
16550
|
-
if (current.type ===
|
|
16551
|
-
if (current.type ===
|
|
16552
|
-
if (current.type ===
|
|
16553
|
-
if (current.type ===
|
|
16554
|
-
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));
|
|
16555
17132
|
return [];
|
|
16556
17133
|
};
|
|
16557
17134
|
const enterFunction = (node) => {
|
|
@@ -16566,8 +17143,8 @@ function createSourceCoupledRule(name, documentation, sourceSuffixRe) {
|
|
|
16566
17143
|
const source = importSource(node);
|
|
16567
17144
|
if (source === null || !FS_MODULES.has(source)) return;
|
|
16568
17145
|
for (const specifier of node.specifiers) {
|
|
16569
|
-
if (specifier.type ===
|
|
16570
|
-
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);
|
|
16571
17148
|
if (FS_READERS.has(imported)) declare(specifier.local.name, { fsReader: true });
|
|
16572
17149
|
} else {
|
|
16573
17150
|
declare(specifier.local.name, { fsObject: true });
|
|
@@ -16579,29 +17156,29 @@ function createSourceCoupledRule(name, documentation, sourceSuffixRe) {
|
|
|
16579
17156
|
VariableDeclarator(node) {
|
|
16580
17157
|
if (node.init === null) return;
|
|
16581
17158
|
const required = requireSource(node.init);
|
|
16582
|
-
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) {
|
|
16583
17160
|
declare(node.id.name, { fsObject: true });
|
|
16584
17161
|
return;
|
|
16585
17162
|
}
|
|
16586
|
-
if (node.id.type ===
|
|
17163
|
+
if (node.id.type === AST_NODE_TYPES71.ObjectPattern && required !== null && FS_MODULES.has(required)) {
|
|
16587
17164
|
for (const property of node.id.properties) {
|
|
16588
|
-
if (property.type !==
|
|
16589
|
-
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) : "";
|
|
16590
17167
|
if (FS_READERS.has(key)) declare(property.value.name, { fsReader: true });
|
|
16591
17168
|
}
|
|
16592
17169
|
return;
|
|
16593
17170
|
}
|
|
16594
|
-
if (node.id.type !==
|
|
17171
|
+
if (node.id.type !== AST_NODE_TYPES71.Identifier) return;
|
|
16595
17172
|
declare(node.id.name, { collection: sourceCollection(node.init), path: sourcePath(node.init), rawOrigins: rawOrigins(node.init) });
|
|
16596
17173
|
},
|
|
16597
17174
|
AssignmentExpression(node) {
|
|
16598
|
-
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) });
|
|
16599
17176
|
},
|
|
16600
17177
|
ForOfStatement(node) {
|
|
16601
|
-
const right =
|
|
16602
|
-
const collection = right.type ===
|
|
16603
|
-
const left = node.left.type ===
|
|
16604
|
-
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 });
|
|
16605
17182
|
},
|
|
16606
17183
|
CallExpression(node) {
|
|
16607
17184
|
const origins = /* @__PURE__ */ new Set([
|
|
@@ -16622,6 +17199,128 @@ var source_coupled_test_default = createSourceCoupledRule(
|
|
|
16622
17199
|
GENERAL_SOURCE_SUFFIX_RE
|
|
16623
17200
|
);
|
|
16624
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
|
+
|
|
16625
17324
|
// src/rules/iac-source-coupled-test.ts
|
|
16626
17325
|
var IAC_SOURCE_SUFFIX_RE = /(?:\.tf\.json|\.tftest\.(?:hcl|json)|\.(?:hcl|tf|tfvars))$/iu;
|
|
16627
17326
|
var IAC_SOURCE_COUPLED_TEST_DOCUMENTATION = {
|
|
@@ -16662,8 +17361,8 @@ var iac_source_coupled_test_default = createSourceCoupledRule(
|
|
|
16662
17361
|
|
|
16663
17362
|
// src/rules/require-pascal-case-zod-schema-name.ts
|
|
16664
17363
|
import {
|
|
16665
|
-
AST_NODE_TYPES as
|
|
16666
|
-
ASTUtils as
|
|
17364
|
+
AST_NODE_TYPES as AST_NODE_TYPES73,
|
|
17365
|
+
ASTUtils as ASTUtils23
|
|
16667
17366
|
} from "@typescript-eslint/utils";
|
|
16668
17367
|
var REQUIRE_PASCAL_CASE_ZOD_SCHEMA_NAME_DOCUMENTATION = {
|
|
16669
17368
|
summary: "Require confirmed module-level Zod schema contracts to use PascalCase with a `Schema` suffix.",
|
|
@@ -16796,18 +17495,18 @@ var SCHEMA_RETURNING_METHODS = /* @__PURE__ */ new Set([
|
|
|
16796
17495
|
"superRefine",
|
|
16797
17496
|
"transform"
|
|
16798
17497
|
]);
|
|
16799
|
-
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;
|
|
16800
17499
|
var calleeChainRoot = (node) => {
|
|
16801
17500
|
let current = node;
|
|
16802
17501
|
for (; ; ) {
|
|
16803
|
-
if (current.type ===
|
|
17502
|
+
if (current.type === AST_NODE_TYPES73.Identifier) {
|
|
16804
17503
|
return current;
|
|
16805
17504
|
}
|
|
16806
|
-
if (current.type ===
|
|
17505
|
+
if (current.type === AST_NODE_TYPES73.MemberExpression) {
|
|
16807
17506
|
current = current.object;
|
|
16808
17507
|
continue;
|
|
16809
17508
|
}
|
|
16810
|
-
if (current.type ===
|
|
17509
|
+
if (current.type === AST_NODE_TYPES73.CallExpression) {
|
|
16811
17510
|
current = current.callee;
|
|
16812
17511
|
continue;
|
|
16813
17512
|
}
|
|
@@ -16818,13 +17517,13 @@ var chainMemberNames = (node) => {
|
|
|
16818
17517
|
const names = [];
|
|
16819
17518
|
let current = node;
|
|
16820
17519
|
for (; ; ) {
|
|
16821
|
-
if (current.type ===
|
|
16822
|
-
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 [];
|
|
16823
17522
|
names.push(current.property.name);
|
|
16824
17523
|
current = current.object;
|
|
16825
17524
|
continue;
|
|
16826
17525
|
}
|
|
16827
|
-
if (current.type ===
|
|
17526
|
+
if (current.type === AST_NODE_TYPES73.CallExpression) {
|
|
16828
17527
|
current = current.callee;
|
|
16829
17528
|
continue;
|
|
16830
17529
|
}
|
|
@@ -16835,16 +17534,16 @@ var chainMemberNames = (node) => {
|
|
|
16835
17534
|
};
|
|
16836
17535
|
var unwrapExpression4 = (node) => {
|
|
16837
17536
|
let current = node;
|
|
16838
|
-
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) {
|
|
16839
17538
|
current = current.expression;
|
|
16840
17539
|
}
|
|
16841
17540
|
return current;
|
|
16842
17541
|
};
|
|
16843
17542
|
var isModuleDeclarator = (node) => {
|
|
16844
17543
|
const declaration = node.parent;
|
|
16845
|
-
if (declaration.type !==
|
|
17544
|
+
if (declaration.type !== AST_NODE_TYPES73.VariableDeclaration) return false;
|
|
16846
17545
|
const owner = declaration.parent;
|
|
16847
|
-
return owner.type ===
|
|
17546
|
+
return owner.type === AST_NODE_TYPES73.Program || owner.type === AST_NODE_TYPES73.ExportNamedDeclaration && owner.parent.type === AST_NODE_TYPES73.Program;
|
|
16848
17547
|
};
|
|
16849
17548
|
var require_pascal_case_zod_schema_name_default = createRule({
|
|
16850
17549
|
name: "require-pascal-case-zod-schema-name",
|
|
@@ -16864,7 +17563,7 @@ var require_pascal_case_zod_schema_name_default = createRule({
|
|
|
16864
17563
|
const zodBindings = /* @__PURE__ */ new Set();
|
|
16865
17564
|
const schemaBindings = /* @__PURE__ */ new Set();
|
|
16866
17565
|
function resolvedBinding(identifier) {
|
|
16867
|
-
return
|
|
17566
|
+
return ASTUtils23.findVariable(
|
|
16868
17567
|
context.sourceCode.getScope(identifier),
|
|
16869
17568
|
identifier.name
|
|
16870
17569
|
);
|
|
@@ -16885,8 +17584,8 @@ var require_pascal_case_zod_schema_name_default = createRule({
|
|
|
16885
17584
|
}
|
|
16886
17585
|
function isConfirmedSchema(expression) {
|
|
16887
17586
|
const init = unwrapExpression4(expression);
|
|
16888
|
-
if (init.type ===
|
|
16889
|
-
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) {
|
|
16890
17589
|
return false;
|
|
16891
17590
|
}
|
|
16892
17591
|
const terminal = terminalMethodName(init.callee);
|
|
@@ -16906,7 +17605,7 @@ var require_pascal_case_zod_schema_name_default = createRule({
|
|
|
16906
17605
|
ImportDeclaration(node) {
|
|
16907
17606
|
if (!isZodModule(node.source.value)) return;
|
|
16908
17607
|
for (const specifier of node.specifiers) {
|
|
16909
|
-
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")) {
|
|
16910
17609
|
recordZodBinding(specifier.local);
|
|
16911
17610
|
}
|
|
16912
17611
|
}
|
|
@@ -16915,7 +17614,7 @@ var require_pascal_case_zod_schema_name_default = createRule({
|
|
|
16915
17614
|
if (!isModuleDeclarator(node)) return;
|
|
16916
17615
|
const init = node.init;
|
|
16917
17616
|
if (init === null || init === void 0) return;
|
|
16918
|
-
if (node.id.type !==
|
|
17617
|
+
if (node.id.type !== AST_NODE_TYPES73.Identifier) return;
|
|
16919
17618
|
if (!isConfirmedSchema(init)) return;
|
|
16920
17619
|
const binding = resolvedBinding(node.id);
|
|
16921
17620
|
if (binding !== null) schemaBindings.add(binding);
|
|
@@ -17073,10 +17772,16 @@ var RULES = {
|
|
|
17073
17772
|
"prefer-shadcn-primitives": prefer_shadcn_primitives_default,
|
|
17074
17773
|
"prefer-module-level-constant": prefer_module_level_constant_default,
|
|
17075
17774
|
"prefer-module-level-schema": prefer_module_level_schema_default,
|
|
17775
|
+
"prefer-named-complex-return-type": prefer_named_complex_return_type_default,
|
|
17076
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,
|
|
17077
17779
|
"prefer-non-nullable-collection": prefer_non_nullable_collection_default,
|
|
17780
|
+
"prefer-nullish-filter-predicate": prefer_nullish_filter_predicate_default,
|
|
17078
17781
|
"prefer-await-in-async-return": prefer_await_in_async_return_default,
|
|
17079
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,
|
|
17080
17785
|
"prefer-semantic-colors": prefer_semantic_colors_default,
|
|
17081
17786
|
"prefer-server-actions": prefer_server_actions_default,
|
|
17082
17787
|
"prefer-whole-object-assertion": prefer_whole_object_assertion_default,
|
|
@@ -17085,23 +17790,33 @@ var RULES = {
|
|
|
17085
17790
|
"require-assert-never": require_assert_never_default,
|
|
17086
17791
|
"require-fetch-timeout": require_fetch_timeout_default,
|
|
17087
17792
|
"require-port-for-service": require_port_for_service_default,
|
|
17793
|
+
"require-sql-access-class": require_sql_access_class_default,
|
|
17088
17794
|
"require-static-next-matcher": require_static_next_matcher_default,
|
|
17089
17795
|
"require-zod-form-validation": require_zod_form_validation_default,
|
|
17090
17796
|
"store-insert-requires-on-conflict": store_insert_requires_on_conflict_default,
|
|
17091
17797
|
"stepdown": stepdown_default,
|
|
17092
17798
|
"source-coupled-test": source_coupled_test_default,
|
|
17799
|
+
"sole-export-matches-filename": sole_export_matches_filename_default,
|
|
17093
17800
|
"require-pascal-case-zod-schema-name": require_pascal_case_zod_schema_name_default
|
|
17094
17801
|
};
|
|
17095
17802
|
var meta = {
|
|
17096
17803
|
name: "@sarj/eslint-plugin",
|
|
17097
|
-
version: "15.
|
|
17804
|
+
version: "15.15.0"
|
|
17098
17805
|
};
|
|
17099
17806
|
var APPLICATION_ONLY_RULES = [
|
|
17100
17807
|
"no-restricted-library-load",
|
|
17101
17808
|
"prefer-native-random-uuid",
|
|
17102
17809
|
"prefer-shadcn-primitives"
|
|
17103
17810
|
];
|
|
17104
|
-
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
|
+
];
|
|
17105
17820
|
var RECOMMENDED_RULES = {
|
|
17106
17821
|
"@sarj/interface-contract-members-private": "error",
|
|
17107
17822
|
"@sarj/iac-source-coupled-test": "error",
|
|
@@ -17155,9 +17870,15 @@ var RECOMMENDED_RULES = {
|
|
|
17155
17870
|
"@sarj/prefer-immutable-module-constant": "error",
|
|
17156
17871
|
"@sarj/prefer-module-level-constant": "error",
|
|
17157
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",
|
|
17158
17876
|
"@sarj/prefer-non-nullable-collection": "error",
|
|
17877
|
+
"@sarj/prefer-nullish-filter-predicate": "error",
|
|
17159
17878
|
"@sarj/prefer-await-in-async-return": "error",
|
|
17160
17879
|
"@sarj/prefer-schema-for-api-payload": "error",
|
|
17880
|
+
"@sarj/prefer-shared-zod-enum": "warn",
|
|
17881
|
+
"@sarj/prefer-switch-for-repeated-equality": "warn",
|
|
17161
17882
|
"@sarj/prefer-semantic-colors": ["error", { requireSemanticTokens: true }],
|
|
17162
17883
|
"@sarj/prefer-server-actions": "error",
|
|
17163
17884
|
"@sarj/prefer-whole-object-assertion": "error",
|
|
@@ -17166,6 +17887,7 @@ var RECOMMENDED_RULES = {
|
|
|
17166
17887
|
"@sarj/require-assert-never": "error",
|
|
17167
17888
|
"@sarj/require-fetch-timeout": "error",
|
|
17168
17889
|
"@sarj/require-port-for-service": "error",
|
|
17890
|
+
"@sarj/require-sql-access-class": "warn",
|
|
17169
17891
|
"@sarj/require-static-next-matcher": "error",
|
|
17170
17892
|
"@sarj/require-use-form-default-values": "error",
|
|
17171
17893
|
"@sarj/require-use-server-in-actions-file": "error",
|
|
@@ -17173,6 +17895,7 @@ var RECOMMENDED_RULES = {
|
|
|
17173
17895
|
"@sarj/store-insert-requires-on-conflict": "error",
|
|
17174
17896
|
"@sarj/stepdown": "error",
|
|
17175
17897
|
"@sarj/source-coupled-test": "error",
|
|
17898
|
+
"@sarj/sole-export-matches-filename": "warn",
|
|
17176
17899
|
"@sarj/test-phase-label-comment": "error",
|
|
17177
17900
|
"@sarj/require-pascal-case-zod-schema-name": "warn"
|
|
17178
17901
|
};
|
|
@@ -17233,9 +17956,15 @@ var STRICT_RULES = {
|
|
|
17233
17956
|
"@sarj/prefer-immutable-module-constant": "error",
|
|
17234
17957
|
"@sarj/prefer-module-level-constant": "error",
|
|
17235
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",
|
|
17236
17962
|
"@sarj/prefer-non-nullable-collection": "error",
|
|
17963
|
+
"@sarj/prefer-nullish-filter-predicate": "error",
|
|
17237
17964
|
"@sarj/prefer-await-in-async-return": "error",
|
|
17238
17965
|
"@sarj/prefer-schema-for-api-payload": "error",
|
|
17966
|
+
"@sarj/prefer-shared-zod-enum": "warn",
|
|
17967
|
+
"@sarj/prefer-switch-for-repeated-equality": "warn",
|
|
17239
17968
|
"@sarj/prefer-semantic-colors": ["error", { requireSemanticTokens: true }],
|
|
17240
17969
|
"@sarj/prefer-server-actions": "error",
|
|
17241
17970
|
"@sarj/prefer-whole-object-assertion": "error",
|
|
@@ -17244,6 +17973,7 @@ var STRICT_RULES = {
|
|
|
17244
17973
|
"@sarj/require-assert-never": "error",
|
|
17245
17974
|
"@sarj/require-fetch-timeout": "error",
|
|
17246
17975
|
"@sarj/require-port-for-service": "error",
|
|
17976
|
+
"@sarj/require-sql-access-class": "warn",
|
|
17247
17977
|
"@sarj/require-static-next-matcher": "error",
|
|
17248
17978
|
"@sarj/require-use-form-default-values": "error",
|
|
17249
17979
|
"@sarj/require-use-server-in-actions-file": "error",
|
|
@@ -17251,6 +17981,7 @@ var STRICT_RULES = {
|
|
|
17251
17981
|
"@sarj/store-insert-requires-on-conflict": "error",
|
|
17252
17982
|
"@sarj/stepdown": "error",
|
|
17253
17983
|
"@sarj/source-coupled-test": "error",
|
|
17984
|
+
"@sarj/sole-export-matches-filename": "warn",
|
|
17254
17985
|
"@sarj/test-phase-label-comment": "error",
|
|
17255
17986
|
"@sarj/require-pascal-case-zod-schema-name": "warn"
|
|
17256
17987
|
};
|