@sarj/eslint-plugin 15.14.0 → 15.16.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 +1678 -676
- package/dist/index.d.cts +35 -3
- package/dist/index.d.ts +35 -3
- package/dist/index.js +1675 -673
- package/package.json +3 -2
package/dist/index.cjs
CHANGED
|
@@ -1274,8 +1274,8 @@ function testCallMatrixStems(comments) {
|
|
|
1274
1274
|
const stems = /* @__PURE__ */ new Set();
|
|
1275
1275
|
for (const comment of comments) {
|
|
1276
1276
|
const body2 = stripCommentMarker(comment.value);
|
|
1277
|
-
const
|
|
1278
|
-
if (
|
|
1277
|
+
const stem4 = CALL_LABEL_RE.exec(body2)?.[1];
|
|
1278
|
+
if (stem4 !== void 0 && MULTIPLIER_PSEUDOCODE_RE.test(body2)) stems.add(stem4);
|
|
1279
1279
|
}
|
|
1280
1280
|
return stems;
|
|
1281
1281
|
}
|
|
@@ -4051,8 +4051,8 @@ function privateMemberFixes(context, services, owner, members, removePrivateKeyw
|
|
|
4051
4051
|
return;
|
|
4052
4052
|
}
|
|
4053
4053
|
if (node.type !== import_utils19.AST_NODE_TYPES.MemberExpression) return;
|
|
4054
|
-
const
|
|
4055
|
-
if (
|
|
4054
|
+
const propertyName7 = node.property.type === import_utils19.AST_NODE_TYPES.Identifier || node.property.type === import_utils19.AST_NODE_TYPES.PrivateIdentifier ? node.property.name : node.property.type === import_utils19.AST_NODE_TYPES.Literal && typeof node.property.value === "string" ? node.property.value : null;
|
|
4055
|
+
if (propertyName7 !== name) return;
|
|
4056
4056
|
const propertySymbol = symbolAt(services, checker, node.property);
|
|
4057
4057
|
if (node.computed || node.property.type !== import_utils19.AST_NODE_TYPES.Identifier || node.object.type !== import_utils19.AST_NODE_TYPES.ThisExpression || enclosingClass(node) !== owner || !symbols.some((symbol) => sameSymbol(symbol, propertySymbol))) {
|
|
4058
4058
|
unsafe = true;
|
|
@@ -4924,8 +4924,8 @@ var CJS_OBJECT_EXPORT_METHODS = /* @__PURE__ */ new Set(["assign", "defineProper
|
|
|
4924
4924
|
function fileParts(filename) {
|
|
4925
4925
|
const base = filename.replaceAll("\\", "/").split("/").at(-1) ?? "";
|
|
4926
4926
|
const extension = base.match(/(\.[cm]?[jt]sx?)$/u)?.[1] ?? ".ts";
|
|
4927
|
-
const [
|
|
4928
|
-
return { stem:
|
|
4927
|
+
const [stem4 = "", ...suffixes] = base.slice(0, -extension.length).split(".");
|
|
4928
|
+
return { stem: stem4, suffixes: suffixes.map((suffix) => suffix.toLowerCase()) };
|
|
4929
4929
|
}
|
|
4930
4930
|
function declaredNames(declaration) {
|
|
4931
4931
|
if (declaration.declare === true) return [];
|
|
@@ -5049,8 +5049,8 @@ var no_generic_single_export_module_default = createRule({
|
|
|
5049
5049
|
defaultOptions: [],
|
|
5050
5050
|
create(context) {
|
|
5051
5051
|
const file = fileParts(context.filename);
|
|
5052
|
-
const { stem:
|
|
5053
|
-
if (!GENERIC_STEMS.has(
|
|
5052
|
+
const { stem: stem4 } = file;
|
|
5053
|
+
if (!GENERIC_STEMS.has(stem4) || isTestFile(context.filename) || isGeneratedFile(context.filename, context.sourceCode.text)) return {};
|
|
5054
5054
|
let hasCommonJsExport = false;
|
|
5055
5055
|
return {
|
|
5056
5056
|
CallExpression(node) {
|
|
@@ -5070,12 +5070,12 @@ var no_generic_single_export_module_default = createRule({
|
|
|
5070
5070
|
const { name: exported, node } = onlyExport;
|
|
5071
5071
|
if (isConventionalFrameworkUtility(context.filename, exported)) return;
|
|
5072
5072
|
const exportedRole = exported.replaceAll(/[^a-z0-9]/giu, "").toLowerCase();
|
|
5073
|
-
const pathRole = [
|
|
5073
|
+
const pathRole = [stem4, ...file.suffixes].join("").replaceAll(/[^a-z0-9]/giu, "");
|
|
5074
5074
|
if (exportedRole === pathRole && file.suffixes.length > 0) return;
|
|
5075
5075
|
context.report({
|
|
5076
5076
|
node,
|
|
5077
5077
|
messageId: "genericSingleExport",
|
|
5078
|
-
data: { stem:
|
|
5078
|
+
data: { stem: stem4, exported }
|
|
5079
5079
|
});
|
|
5080
5080
|
}
|
|
5081
5081
|
};
|
|
@@ -5392,7 +5392,7 @@ var no_positional_tuple_return_default = createRule({
|
|
|
5392
5392
|
const aliases = typeAliases(context.sourceCode.ast);
|
|
5393
5393
|
const reportedFunctions = /* @__PURE__ */ new WeakSet();
|
|
5394
5394
|
const functionStack = [];
|
|
5395
|
-
const
|
|
5395
|
+
const report2 = (annotation, name) => {
|
|
5396
5396
|
const tuple = tupleReturnType(annotation, aliases);
|
|
5397
5397
|
if (tuple === null || tuple.elementTypes.length < MIN_ELEMENTS) return;
|
|
5398
5398
|
context.report({
|
|
@@ -5426,7 +5426,7 @@ var no_positional_tuple_return_default = createRule({
|
|
|
5426
5426
|
if (name === null) {
|
|
5427
5427
|
return;
|
|
5428
5428
|
}
|
|
5429
|
-
|
|
5429
|
+
report2(annotation, name);
|
|
5430
5430
|
};
|
|
5431
5431
|
const enterFunction = (node) => {
|
|
5432
5432
|
functionStack.push(node);
|
|
@@ -5451,34 +5451,34 @@ var no_positional_tuple_return_default = createRule({
|
|
|
5451
5451
|
},
|
|
5452
5452
|
TSDeclareFunction(node) {
|
|
5453
5453
|
if (node.id === null || node.returnType === void 0 || node.parent.type !== import_utils28.AST_NODE_TYPES.ExportNamedDeclaration && node.parent.type !== import_utils28.AST_NODE_TYPES.ExportDefaultDeclaration && !specifierExports.has(node.id.name)) return;
|
|
5454
|
-
|
|
5454
|
+
report2(node.returnType.typeAnnotation, node.id.name);
|
|
5455
5455
|
},
|
|
5456
5456
|
TSCallSignatureDeclaration(node) {
|
|
5457
5457
|
const owner = owningInterface(node);
|
|
5458
5458
|
if (owner === null || !isExportedInterface(owner, typeExports) || node.returnType === void 0) return;
|
|
5459
|
-
|
|
5459
|
+
report2(node.returnType.typeAnnotation, `${owner.id.name}.call`);
|
|
5460
5460
|
},
|
|
5461
5461
|
TSMethodSignature(node) {
|
|
5462
5462
|
const owner = owningInterface(node);
|
|
5463
5463
|
const alias = owningTypeAlias(node);
|
|
5464
|
-
const
|
|
5465
|
-
if ((owner === null || !isExportedInterface(owner, typeExports)) && (alias === null || !typeExports.has(alias.id.name)) || node.returnType === void 0 ||
|
|
5466
|
-
|
|
5464
|
+
const memberName6 = staticMemberName3(node.key);
|
|
5465
|
+
if ((owner === null || !isExportedInterface(owner, typeExports)) && (alias === null || !typeExports.has(alias.id.name)) || node.returnType === void 0 || memberName6 === null) return;
|
|
5466
|
+
report2(node.returnType.typeAnnotation, `${owner?.id.name ?? alias?.id.name ?? "type"}.${memberName6}`);
|
|
5467
5467
|
},
|
|
5468
5468
|
TSTypeAliasDeclaration(node) {
|
|
5469
5469
|
if (!typeExports.has(node.id.name)) return;
|
|
5470
5470
|
const returnType = callableReturnType(node.typeAnnotation, aliases);
|
|
5471
|
-
if (returnType !== null)
|
|
5471
|
+
if (returnType !== null) report2(returnType, node.id.name);
|
|
5472
5472
|
},
|
|
5473
5473
|
TSPropertySignature(node) {
|
|
5474
5474
|
const owner = owningInterface(node);
|
|
5475
5475
|
const alias = owningTypeAlias(node);
|
|
5476
5476
|
const annotation = node.typeAnnotation?.typeAnnotation;
|
|
5477
|
-
const
|
|
5478
|
-
if ((owner === null || !isExportedInterface(owner, typeExports)) && (alias === null || !typeExports.has(alias.id.name)) ||
|
|
5477
|
+
const memberName6 = staticMemberName3(node.key);
|
|
5478
|
+
if ((owner === null || !isExportedInterface(owner, typeExports)) && (alias === null || !typeExports.has(alias.id.name)) || memberName6 === null || annotation === void 0) return;
|
|
5479
5479
|
const returnType = callableReturnType(annotation, aliases);
|
|
5480
5480
|
if (returnType !== null) {
|
|
5481
|
-
|
|
5481
|
+
report2(returnType, `${owner?.id.name ?? alias?.id.name ?? "type"}.${memberName6}`);
|
|
5482
5482
|
}
|
|
5483
5483
|
},
|
|
5484
5484
|
PropertyDefinition(node) {
|
|
@@ -5489,7 +5489,7 @@ var no_positional_tuple_return_default = createRule({
|
|
|
5489
5489
|
const returnType = callableReturnType(annotation, aliases);
|
|
5490
5490
|
if (returnType !== null) {
|
|
5491
5491
|
const name = node.key.type === import_utils28.AST_NODE_TYPES.Identifier ? node.key.name : "property";
|
|
5492
|
-
|
|
5492
|
+
report2(returnType, name);
|
|
5493
5493
|
}
|
|
5494
5494
|
}
|
|
5495
5495
|
};
|
|
@@ -5965,7 +5965,7 @@ var no_restricted_library_load_default = createRule({
|
|
|
5965
5965
|
defaultOptions: [{ libraries: [] }],
|
|
5966
5966
|
create(context, [options]) {
|
|
5967
5967
|
const restrictions = options.libraries;
|
|
5968
|
-
function
|
|
5968
|
+
function report2(node, source) {
|
|
5969
5969
|
const restriction = restrictions.find(
|
|
5970
5970
|
(entry) => matchesModule(source, entry.module)
|
|
5971
5971
|
);
|
|
@@ -5991,7 +5991,7 @@ var no_restricted_library_load_default = createRule({
|
|
|
5991
5991
|
return {
|
|
5992
5992
|
ImportExpression(node) {
|
|
5993
5993
|
const source = literalModule(node.source);
|
|
5994
|
-
if (source !== null)
|
|
5994
|
+
if (source !== null) report2(node.source, source);
|
|
5995
5995
|
},
|
|
5996
5996
|
CallExpression(node) {
|
|
5997
5997
|
let requireIdentifier = null;
|
|
@@ -6002,12 +6002,12 @@ var no_restricted_library_load_default = createRule({
|
|
|
6002
6002
|
}
|
|
6003
6003
|
if (requireIdentifier === null || !isUnshadowedRequire(requireIdentifier)) return;
|
|
6004
6004
|
const source = literalModule(node.arguments[0]);
|
|
6005
|
-
if (source !== null)
|
|
6005
|
+
if (source !== null) report2(node.arguments[0], source);
|
|
6006
6006
|
},
|
|
6007
6007
|
TSImportEqualsDeclaration(node) {
|
|
6008
6008
|
if (node.moduleReference.type !== import_utils32.AST_NODE_TYPES.TSExternalModuleReference) return;
|
|
6009
6009
|
const source = literalModule(node.moduleReference.expression);
|
|
6010
|
-
if (source !== null)
|
|
6010
|
+
if (source !== null) report2(node.moduleReference.expression, source);
|
|
6011
6011
|
}
|
|
6012
6012
|
};
|
|
6013
6013
|
}
|
|
@@ -7823,7 +7823,7 @@ var no_sleep_in_test_body_default = createRule({
|
|
|
7823
7823
|
if (!isTestFile(context.filename)) {
|
|
7824
7824
|
return {};
|
|
7825
7825
|
}
|
|
7826
|
-
const
|
|
7826
|
+
const report2 = (node) => {
|
|
7827
7827
|
if (!isImmediatelyConsumedSleep(node)) {
|
|
7828
7828
|
return;
|
|
7829
7829
|
}
|
|
@@ -7836,12 +7836,12 @@ var no_sleep_in_test_body_default = createRule({
|
|
|
7836
7836
|
return {
|
|
7837
7837
|
NewExpression(node) {
|
|
7838
7838
|
if (isPromiseSleep(node)) {
|
|
7839
|
-
|
|
7839
|
+
report2(node);
|
|
7840
7840
|
}
|
|
7841
7841
|
},
|
|
7842
7842
|
CallExpression(node) {
|
|
7843
7843
|
if (isHelperSleep(node)) {
|
|
7844
|
-
|
|
7844
|
+
report2(node);
|
|
7845
7845
|
}
|
|
7846
7846
|
}
|
|
7847
7847
|
};
|
|
@@ -10282,7 +10282,7 @@ function reportClass2(context, services, owner) {
|
|
|
10282
10282
|
}
|
|
10283
10283
|
function isConvertible(member) {
|
|
10284
10284
|
if (member.type !== import_utils58.AST_NODE_TYPES.MethodDefinition && member.type !== import_utils58.AST_NODE_TYPES.PropertyDefinition && member.type !== import_utils58.AST_NODE_TYPES.AccessorProperty) return false;
|
|
10285
|
-
return member.accessibility === "private" && !member.computed && member.key.type === import_utils58.AST_NODE_TYPES.Identifier && member.decorators.length === 0 && !("declare" in member && member.declare) && !member.override && !(member.type === import_utils58.AST_NODE_TYPES.MethodDefinition && member.value.body === null);
|
|
10285
|
+
return member.accessibility === "private" && !(member.type === import_utils58.AST_NODE_TYPES.MethodDefinition && member.kind === "constructor") && !member.computed && member.key.type === import_utils58.AST_NODE_TYPES.Identifier && member.decorators.length === 0 && !("declare" in member && member.declare) && !member.override && !(member.type === import_utils58.AST_NODE_TYPES.MethodDefinition && member.value.body === null);
|
|
10286
10286
|
}
|
|
10287
10287
|
var prefer_ecmascript_private_members_default = createRule({
|
|
10288
10288
|
name: "prefer-ecmascript-private-members",
|
|
@@ -10480,9 +10480,9 @@ var INPUT_MODULE = /(?:^|\/)components\/ui\/input$/u;
|
|
|
10480
10480
|
var INPUT_GROUP_MODULE = /(?:^|\/)components\/ui\/input-group$/u;
|
|
10481
10481
|
var MAX_JSX_DISTANCE = 2;
|
|
10482
10482
|
var SEARCH_EXPORTS = ["Search", "SearchIcon", "LucideSearch"];
|
|
10483
|
-
function localNamedImports(node,
|
|
10483
|
+
function localNamedImports(node, importedName7) {
|
|
10484
10484
|
return node.specifiers.filter(
|
|
10485
|
-
(specifier) => specifier.type === import_utils61.AST_NODE_TYPES.ImportSpecifier && (specifier.imported.type === import_utils61.AST_NODE_TYPES.Identifier ? specifier.imported.name : specifier.imported.value) ===
|
|
10485
|
+
(specifier) => specifier.type === import_utils61.AST_NODE_TYPES.ImportSpecifier && (specifier.imported.type === import_utils61.AST_NODE_TYPES.Identifier ? specifier.imported.name : specifier.imported.value) === importedName7
|
|
10486
10486
|
).map((specifier) => specifier.local.name);
|
|
10487
10487
|
}
|
|
10488
10488
|
function elementName(node) {
|
|
@@ -11695,8 +11695,67 @@ var prefer_module_level_schema_default = createRule({
|
|
|
11695
11695
|
}
|
|
11696
11696
|
});
|
|
11697
11697
|
|
|
11698
|
-
// src/rules/prefer-
|
|
11698
|
+
// src/rules/prefer-named-complex-return-type.ts
|
|
11699
11699
|
var import_utils66 = require("@typescript-eslint/utils");
|
|
11700
|
+
var PREFER_NAMED_COMPLEX_RETURN_TYPE_DOCUMENTATION = {
|
|
11701
|
+
summary: "Prefer a named contract for structurally complex function return types.",
|
|
11702
|
+
rationale: "A large inline return annotation hides a reusable domain concept and makes signatures difficult to scan.",
|
|
11703
|
+
remediation: "Extract the return annotation to a named type or interface and reference that contract from the signature.",
|
|
11704
|
+
category: "maintainability",
|
|
11705
|
+
limitations: [
|
|
11706
|
+
"Only explicit object types with at least three members and unions with at least three object variants are reported.",
|
|
11707
|
+
"Generic wrappers such as Promise and Readonly are unwrapped one level at a time; inferred return types are outside this rule."
|
|
11708
|
+
],
|
|
11709
|
+
examples: [
|
|
11710
|
+
{ 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 },
|
|
11711
|
+
{ 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 }
|
|
11712
|
+
]
|
|
11713
|
+
};
|
|
11714
|
+
function unwrap4(node) {
|
|
11715
|
+
if (node.type === import_utils66.AST_NODE_TYPES.TSTypeReference && node.typeArguments?.params.length === 1) {
|
|
11716
|
+
const [inner] = node.typeArguments.params;
|
|
11717
|
+
if (inner !== void 0) return unwrap4(inner);
|
|
11718
|
+
}
|
|
11719
|
+
return node;
|
|
11720
|
+
}
|
|
11721
|
+
function report(context, node) {
|
|
11722
|
+
const annotation = node.returnType?.typeAnnotation;
|
|
11723
|
+
if (annotation !== void 0 && isComplex(annotation)) {
|
|
11724
|
+
context.report({ node: annotation, messageId: "nameComplexReturnType" });
|
|
11725
|
+
}
|
|
11726
|
+
}
|
|
11727
|
+
function isComplex(node) {
|
|
11728
|
+
const type = unwrap4(node);
|
|
11729
|
+
if (type.type === import_utils66.AST_NODE_TYPES.TSTypeLiteral) return type.members.length >= 3;
|
|
11730
|
+
if (type.type !== import_utils66.AST_NODE_TYPES.TSUnionType || type.types.length < 3) return false;
|
|
11731
|
+
return type.types.every((member) => unwrap4(member).type === import_utils66.AST_NODE_TYPES.TSTypeLiteral);
|
|
11732
|
+
}
|
|
11733
|
+
var prefer_named_complex_return_type_default = createRule({
|
|
11734
|
+
name: "prefer-named-complex-return-type",
|
|
11735
|
+
documentation: PREFER_NAMED_COMPLEX_RETURN_TYPE_DOCUMENTATION,
|
|
11736
|
+
meta: {
|
|
11737
|
+
type: "suggestion",
|
|
11738
|
+
docs: { description: "Prefer a named contract for structurally complex function return types." },
|
|
11739
|
+
schema: [],
|
|
11740
|
+
messages: {
|
|
11741
|
+
nameComplexReturnType: "Extract this structurally complex return annotation to a named type or interface."
|
|
11742
|
+
}
|
|
11743
|
+
},
|
|
11744
|
+
defaultOptions: [],
|
|
11745
|
+
create(context) {
|
|
11746
|
+
if (isTestFile(context.filename) || isGeneratedFile(context.filename, context.sourceCode.text)) return {};
|
|
11747
|
+
return {
|
|
11748
|
+
ArrowFunctionExpression: (node) => report(context, node),
|
|
11749
|
+
FunctionDeclaration: (node) => report(context, node),
|
|
11750
|
+
FunctionExpression: (node) => report(context, node),
|
|
11751
|
+
TSDeclareFunction: (node) => report(context, node),
|
|
11752
|
+
TSMethodSignature: (node) => report(context, node)
|
|
11753
|
+
};
|
|
11754
|
+
}
|
|
11755
|
+
});
|
|
11756
|
+
|
|
11757
|
+
// src/rules/prefer-native-random-uuid.ts
|
|
11758
|
+
var import_utils67 = require("@typescript-eslint/utils");
|
|
11700
11759
|
var PREFER_NATIVE_RANDOM_UUID_DOCUMENTATION = {
|
|
11701
11760
|
summary: "Prefer `globalThis.crypto.randomUUID()` over resolved zero-argument UUID v4 bindings from the `uuid` package.",
|
|
11702
11761
|
rationale: "The platform implementation avoids an unnecessary dependency for standard random UUID generation.",
|
|
@@ -11710,7 +11769,7 @@ var PREFER_NATIVE_RANDOM_UUID_DOCUMENTATION = {
|
|
|
11710
11769
|
]
|
|
11711
11770
|
};
|
|
11712
11771
|
function requireUuid(node) {
|
|
11713
|
-
return node?.type ===
|
|
11772
|
+
return node?.type === import_utils67.AST_NODE_TYPES.CallExpression && node.callee.type === import_utils67.AST_NODE_TYPES.Identifier && node.callee.name === "require" && node.arguments.length === 1 && node.arguments[0]?.type === import_utils67.AST_NODE_TYPES.Literal && node.arguments[0].value === "uuid";
|
|
11714
11773
|
}
|
|
11715
11774
|
var prefer_native_random_uuid_default = createRule({
|
|
11716
11775
|
name: "prefer-native-random-uuid",
|
|
@@ -11732,13 +11791,13 @@ var prefer_native_random_uuid_default = createRule({
|
|
|
11732
11791
|
const directBindings = /* @__PURE__ */ new Set();
|
|
11733
11792
|
const namespaceBindings = /* @__PURE__ */ new Set();
|
|
11734
11793
|
function resolve(identifier) {
|
|
11735
|
-
return
|
|
11794
|
+
return import_utils67.ASTUtils.findVariable(context.sourceCode.getScope(identifier), identifier.name);
|
|
11736
11795
|
}
|
|
11737
11796
|
function record(identifier, destination) {
|
|
11738
11797
|
const variable = resolve(identifier);
|
|
11739
11798
|
if (variable !== null) destination.add(variable);
|
|
11740
11799
|
}
|
|
11741
|
-
function
|
|
11800
|
+
function report2(node) {
|
|
11742
11801
|
context.report({
|
|
11743
11802
|
node,
|
|
11744
11803
|
messageId: "preferNative",
|
|
@@ -11754,48 +11813,291 @@ var prefer_native_random_uuid_default = createRule({
|
|
|
11754
11813
|
ImportDeclaration(node) {
|
|
11755
11814
|
if (node.source.value !== "uuid") return;
|
|
11756
11815
|
for (const specifier of node.specifiers) {
|
|
11757
|
-
if (specifier.type ===
|
|
11816
|
+
if (specifier.type === import_utils67.AST_NODE_TYPES.ImportSpecifier && (specifier.imported.type === import_utils67.AST_NODE_TYPES.Identifier ? specifier.imported.name === "v4" : specifier.imported.value === "v4")) {
|
|
11758
11817
|
record(specifier.local, directBindings);
|
|
11759
|
-
} else if (specifier.type ===
|
|
11818
|
+
} else if (specifier.type === import_utils67.AST_NODE_TYPES.ImportNamespaceSpecifier) {
|
|
11760
11819
|
record(specifier.local, namespaceBindings);
|
|
11761
11820
|
}
|
|
11762
11821
|
}
|
|
11763
11822
|
},
|
|
11764
11823
|
VariableDeclarator(node) {
|
|
11765
11824
|
if (node.parent.kind !== "const" || !requireUuid(node.init)) return;
|
|
11766
|
-
if (node.init?.type !==
|
|
11825
|
+
if (node.init?.type !== import_utils67.AST_NODE_TYPES.CallExpression || node.init.callee.type !== import_utils67.AST_NODE_TYPES.Identifier || (resolve(node.init.callee)?.defs.length ?? 0) > 0) {
|
|
11767
11826
|
return;
|
|
11768
11827
|
}
|
|
11769
|
-
if (node.id.type ===
|
|
11828
|
+
if (node.id.type === import_utils67.AST_NODE_TYPES.Identifier) {
|
|
11770
11829
|
record(node.id, namespaceBindings);
|
|
11771
11830
|
return;
|
|
11772
11831
|
}
|
|
11773
|
-
if (node.id.type !==
|
|
11832
|
+
if (node.id.type !== import_utils67.AST_NODE_TYPES.ObjectPattern) return;
|
|
11774
11833
|
for (const property of node.id.properties) {
|
|
11775
|
-
if (property.type ===
|
|
11834
|
+
if (property.type === import_utils67.AST_NODE_TYPES.Property && !property.computed && (property.key.type === import_utils67.AST_NODE_TYPES.Identifier && property.key.name === "v4" || property.key.type === import_utils67.AST_NODE_TYPES.Literal && property.key.value === "v4") && property.value.type === import_utils67.AST_NODE_TYPES.Identifier) {
|
|
11776
11835
|
record(property.value, directBindings);
|
|
11777
11836
|
}
|
|
11778
11837
|
}
|
|
11779
11838
|
},
|
|
11780
11839
|
"CallExpression:exit"(node) {
|
|
11781
11840
|
if (node.arguments.length !== 0) return;
|
|
11782
|
-
if (node.callee.type ===
|
|
11841
|
+
if (node.callee.type === import_utils67.AST_NODE_TYPES.Identifier) {
|
|
11783
11842
|
const variable2 = resolve(node.callee);
|
|
11784
|
-
if (variable2 !== null && directBindings.has(variable2))
|
|
11843
|
+
if (variable2 !== null && directBindings.has(variable2)) report2(node);
|
|
11785
11844
|
return;
|
|
11786
11845
|
}
|
|
11787
|
-
if (node.callee.type !==
|
|
11846
|
+
if (node.callee.type !== import_utils67.AST_NODE_TYPES.MemberExpression || node.callee.computed || node.callee.object.type !== import_utils67.AST_NODE_TYPES.Identifier || node.callee.property.type !== import_utils67.AST_NODE_TYPES.Identifier || node.callee.property.name !== "v4") {
|
|
11788
11847
|
return;
|
|
11789
11848
|
}
|
|
11790
11849
|
const variable = resolve(node.callee.object);
|
|
11791
|
-
if (variable !== null && namespaceBindings.has(variable))
|
|
11850
|
+
if (variable !== null && namespaceBindings.has(variable)) report2(node);
|
|
11851
|
+
}
|
|
11852
|
+
};
|
|
11853
|
+
}
|
|
11854
|
+
});
|
|
11855
|
+
|
|
11856
|
+
// src/rules/prefer-node-crypto-hash.ts
|
|
11857
|
+
var import_utils68 = require("@typescript-eslint/utils");
|
|
11858
|
+
var PREFER_NODE_CRYPTO_HASH_DOCUMENTATION = {
|
|
11859
|
+
summary: "Prefer the modern one-shot node:crypto hash API when streaming state is unnecessary.",
|
|
11860
|
+
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.",
|
|
11861
|
+
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.",
|
|
11862
|
+
category: "performance",
|
|
11863
|
+
limitations: [
|
|
11864
|
+
"Only bindings and inline calls with statically proven provenance from crypto or node:crypto are analyzed; arbitrary assignments and dynamic module specifiers are excluded.",
|
|
11865
|
+
"Only a literal algorithm with exactly one update call is reported; streaming and incremental hashes remain valid."
|
|
11866
|
+
],
|
|
11867
|
+
examples: [
|
|
11868
|
+
{ 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 },
|
|
11869
|
+
{ 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 }
|
|
11870
|
+
]
|
|
11871
|
+
};
|
|
11872
|
+
function memberName3(node) {
|
|
11873
|
+
if (!node.computed && node.property.type === import_utils68.AST_NODE_TYPES.Identifier) return node.property.name;
|
|
11874
|
+
if (node.computed && node.property.type === import_utils68.AST_NODE_TYPES.Literal && typeof node.property.value === "string") {
|
|
11875
|
+
return node.property.value;
|
|
11876
|
+
}
|
|
11877
|
+
return null;
|
|
11878
|
+
}
|
|
11879
|
+
function isCryptoLoader(node, resolve) {
|
|
11880
|
+
if (node.type !== import_utils68.AST_NODE_TYPES.CallExpression || node.arguments.length !== 1) return false;
|
|
11881
|
+
const [argument] = node.arguments;
|
|
11882
|
+
if (argument === void 0 || argument.type === import_utils68.AST_NODE_TYPES.SpreadElement || !isCryptoSpecifier(argument)) {
|
|
11883
|
+
return false;
|
|
11884
|
+
}
|
|
11885
|
+
if (node.callee.type === import_utils68.AST_NODE_TYPES.Identifier) {
|
|
11886
|
+
return node.callee.name === "require" && isUnshadowedBuiltinIdentifier(node.callee, resolve);
|
|
11887
|
+
}
|
|
11888
|
+
return node.callee.type === import_utils68.AST_NODE_TYPES.MemberExpression && node.callee.object.type === import_utils68.AST_NODE_TYPES.Identifier && node.callee.object.name === "process" && isUnshadowedBuiltinIdentifier(node.callee.object, resolve) && memberName3(node.callee) === "getBuiltinModule";
|
|
11889
|
+
}
|
|
11890
|
+
function isCryptoSpecifier(node) {
|
|
11891
|
+
return node.type === import_utils68.AST_NODE_TYPES.Literal && (node.value === "crypto" || node.value === "node:crypto");
|
|
11892
|
+
}
|
|
11893
|
+
function isUnshadowedBuiltinIdentifier(identifier, resolve) {
|
|
11894
|
+
const variable = resolve(identifier);
|
|
11895
|
+
return variable === null || variable.defs.length === 0;
|
|
11896
|
+
}
|
|
11897
|
+
function propertyName3(node) {
|
|
11898
|
+
if (!node.computed && node.key.type === import_utils68.AST_NODE_TYPES.Identifier) return node.key.name;
|
|
11899
|
+
if (node.key.type === import_utils68.AST_NODE_TYPES.Literal && typeof node.key.value === "string") {
|
|
11900
|
+
return node.key.value;
|
|
11901
|
+
}
|
|
11902
|
+
return null;
|
|
11903
|
+
}
|
|
11904
|
+
var prefer_node_crypto_hash_default = createRule({
|
|
11905
|
+
name: "prefer-node-crypto-hash",
|
|
11906
|
+
documentation: PREFER_NODE_CRYPTO_HASH_DOCUMENTATION,
|
|
11907
|
+
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." } },
|
|
11908
|
+
defaultOptions: [],
|
|
11909
|
+
create(context) {
|
|
11910
|
+
const directBindings = /* @__PURE__ */ new Set();
|
|
11911
|
+
const namespaceBindings = /* @__PURE__ */ new Set();
|
|
11912
|
+
function resolve(identifier) {
|
|
11913
|
+
return import_utils68.ASTUtils.findVariable(
|
|
11914
|
+
context.sourceCode.getScope(identifier),
|
|
11915
|
+
identifier.name
|
|
11916
|
+
);
|
|
11917
|
+
}
|
|
11918
|
+
function record(identifier, destination) {
|
|
11919
|
+
const variable = resolve(identifier);
|
|
11920
|
+
if (variable !== null) destination.add(variable);
|
|
11921
|
+
}
|
|
11922
|
+
return {
|
|
11923
|
+
ImportDeclaration(node) {
|
|
11924
|
+
if (node.source.value !== "crypto" && node.source.value !== "node:crypto") return;
|
|
11925
|
+
for (const specifier of node.specifiers) {
|
|
11926
|
+
if (specifier.type === import_utils68.AST_NODE_TYPES.ImportNamespaceSpecifier || specifier.type === import_utils68.AST_NODE_TYPES.ImportDefaultSpecifier) {
|
|
11927
|
+
record(specifier.local, namespaceBindings);
|
|
11928
|
+
} else if (specifier.type === import_utils68.AST_NODE_TYPES.ImportSpecifier && importedName5(specifier.imported) === "createHash") {
|
|
11929
|
+
record(specifier.local, directBindings);
|
|
11930
|
+
}
|
|
11931
|
+
}
|
|
11932
|
+
},
|
|
11933
|
+
VariableDeclarator(node) {
|
|
11934
|
+
if (node.parent.kind !== "const" || node.init === null || !isCryptoLoader(node.init, resolve)) {
|
|
11935
|
+
return;
|
|
11936
|
+
}
|
|
11937
|
+
if (node.id.type === import_utils68.AST_NODE_TYPES.Identifier) {
|
|
11938
|
+
record(node.id, namespaceBindings);
|
|
11939
|
+
return;
|
|
11940
|
+
}
|
|
11941
|
+
if (node.id.type !== import_utils68.AST_NODE_TYPES.ObjectPattern) return;
|
|
11942
|
+
for (const property of node.id.properties) {
|
|
11943
|
+
if (property.type === import_utils68.AST_NODE_TYPES.Property && propertyName3(property) === "createHash" && property.value.type === import_utils68.AST_NODE_TYPES.Identifier) {
|
|
11944
|
+
record(property.value, directBindings);
|
|
11945
|
+
}
|
|
11946
|
+
}
|
|
11947
|
+
},
|
|
11948
|
+
CallExpression(node) {
|
|
11949
|
+
if (!isMemberCall(node, "digest")) return;
|
|
11950
|
+
const update = node.callee.object;
|
|
11951
|
+
if (update.type !== import_utils68.AST_NODE_TYPES.CallExpression || update.arguments.length !== 1 || !isMemberCall(update, "update"))
|
|
11952
|
+
return;
|
|
11953
|
+
const create = update.callee.object;
|
|
11954
|
+
if (create.type !== import_utils68.AST_NODE_TYPES.CallExpression || create.arguments.length !== 1 || create.arguments[0]?.type !== import_utils68.AST_NODE_TYPES.Literal || typeof create.arguments[0].value !== "string" || !isCreateHashCall(
|
|
11955
|
+
create,
|
|
11956
|
+
directBindings,
|
|
11957
|
+
namespaceBindings,
|
|
11958
|
+
resolve
|
|
11959
|
+
))
|
|
11960
|
+
return;
|
|
11961
|
+
context.report({ node, messageId: "preferNodeCryptoHash" });
|
|
11962
|
+
}
|
|
11963
|
+
};
|
|
11964
|
+
}
|
|
11965
|
+
});
|
|
11966
|
+
function importedName5(node) {
|
|
11967
|
+
return node.type === import_utils68.AST_NODE_TYPES.Identifier ? node.name : node.value;
|
|
11968
|
+
}
|
|
11969
|
+
function isMemberCall(node, name) {
|
|
11970
|
+
return node.callee.type === import_utils68.AST_NODE_TYPES.MemberExpression && memberName3(node.callee) === name;
|
|
11971
|
+
}
|
|
11972
|
+
function isCreateHashCall(node, directBindings, namespaceBindings, resolve) {
|
|
11973
|
+
if (node.callee.type === import_utils68.AST_NODE_TYPES.Identifier) {
|
|
11974
|
+
const variable2 = resolve(node.callee);
|
|
11975
|
+
return variable2 !== null && directBindings.has(variable2);
|
|
11976
|
+
}
|
|
11977
|
+
if (node.callee.type !== import_utils68.AST_NODE_TYPES.MemberExpression || memberName3(node.callee) !== "createHash") {
|
|
11978
|
+
return false;
|
|
11979
|
+
}
|
|
11980
|
+
if (isCryptoLoader(node.callee.object, resolve)) return true;
|
|
11981
|
+
if (node.callee.object.type !== import_utils68.AST_NODE_TYPES.Identifier) return false;
|
|
11982
|
+
const variable = resolve(node.callee.object);
|
|
11983
|
+
return variable !== null && namespaceBindings.has(variable);
|
|
11984
|
+
}
|
|
11985
|
+
|
|
11986
|
+
// src/rules/prefer-node-fs-promises.ts
|
|
11987
|
+
var import_utils69 = require("@typescript-eslint/utils");
|
|
11988
|
+
var PREFER_NODE_FS_PROMISES_DOCUMENTATION = {
|
|
11989
|
+
summary: "Prefer promise-based Node.js filesystem APIs over synchronous calls in production modules.",
|
|
11990
|
+
rationale: "Synchronous filesystem work blocks the event loop and can stall unrelated daemon, server, and worker tasks.",
|
|
11991
|
+
remediation: "Import the promise API from node:fs/promises and await it; use FileHandle.sync only where a documented durability boundary requires it.",
|
|
11992
|
+
category: "performance",
|
|
11993
|
+
limitations: [
|
|
11994
|
+
"Tests and generated files are excluded.",
|
|
11995
|
+
"ESLint rule implementations under src/rules are excluded because visitor creation and execution are synchronous by contract.",
|
|
11996
|
+
"Only statically identifiable node:fs loads are inspected; filesystem objects passed through arbitrary functions or assignments require type-aware analysis."
|
|
11997
|
+
],
|
|
11998
|
+
examples: [
|
|
11999
|
+
{ 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 },
|
|
12000
|
+
{ 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 }
|
|
12001
|
+
]
|
|
12002
|
+
};
|
|
12003
|
+
function memberName4(node) {
|
|
12004
|
+
if (!node.computed && node.property.type === import_utils69.AST_NODE_TYPES.Identifier) return node.property.name;
|
|
12005
|
+
if (node.computed && node.property.type === import_utils69.AST_NODE_TYPES.Literal && typeof node.property.value === "string") {
|
|
12006
|
+
return node.property.value;
|
|
12007
|
+
}
|
|
12008
|
+
return null;
|
|
12009
|
+
}
|
|
12010
|
+
function unwrapAwait2(node) {
|
|
12011
|
+
return node.type === import_utils69.AST_NODE_TYPES.AwaitExpression ? node.argument : node;
|
|
12012
|
+
}
|
|
12013
|
+
function isFsLoader(node) {
|
|
12014
|
+
const expression = unwrapAwait2(node);
|
|
12015
|
+
if (expression.type === import_utils69.AST_NODE_TYPES.ImportExpression) return isFsSpecifier(expression.source);
|
|
12016
|
+
if (expression.type !== import_utils69.AST_NODE_TYPES.CallExpression || expression.arguments.length !== 1) return false;
|
|
12017
|
+
const [argument] = expression.arguments;
|
|
12018
|
+
if (argument === void 0 || argument.type === import_utils69.AST_NODE_TYPES.SpreadElement || !isFsSpecifier(argument)) return false;
|
|
12019
|
+
if (expression.callee.type === import_utils69.AST_NODE_TYPES.Identifier) return expression.callee.name === "require";
|
|
12020
|
+
return expression.callee.type === import_utils69.AST_NODE_TYPES.MemberExpression && expression.callee.object.type === import_utils69.AST_NODE_TYPES.Identifier && expression.callee.object.name === "process" && memberName4(expression.callee) === "getBuiltinModule";
|
|
12021
|
+
}
|
|
12022
|
+
function isFsSpecifier(node) {
|
|
12023
|
+
return node.type === import_utils69.AST_NODE_TYPES.Literal && (node.value === "node:fs" || node.value === "fs");
|
|
12024
|
+
}
|
|
12025
|
+
function propertyName4(node) {
|
|
12026
|
+
if (!node.computed && node.key.type === import_utils69.AST_NODE_TYPES.Identifier) return node.key.name;
|
|
12027
|
+
if (node.key.type === import_utils69.AST_NODE_TYPES.Literal && typeof node.key.value === "string") return node.key.value;
|
|
12028
|
+
return null;
|
|
12029
|
+
}
|
|
12030
|
+
var prefer_node_fs_promises_default = createRule({
|
|
12031
|
+
name: "prefer-node-fs-promises",
|
|
12032
|
+
documentation: PREFER_NODE_FS_PROMISES_DOCUMENTATION,
|
|
12033
|
+
meta: {
|
|
12034
|
+
type: "suggestion",
|
|
12035
|
+
docs: { description: "Prefer promise-based Node.js filesystem APIs over synchronous calls in production modules." },
|
|
12036
|
+
schema: [],
|
|
12037
|
+
messages: {
|
|
12038
|
+
preferAsyncFs: "Node filesystem API `{{name}}` is synchronous; use the promise API and await it."
|
|
12039
|
+
}
|
|
12040
|
+
},
|
|
12041
|
+
defaultOptions: [],
|
|
12042
|
+
create(context) {
|
|
12043
|
+
const normalizedFilename = context.filename.replaceAll("\\", "/");
|
|
12044
|
+
if (isTestFile(context.filename) || isGeneratedFile(context.filename, context.sourceCode.text) || normalizedFilename.includes("src/rules/"))
|
|
12045
|
+
return {};
|
|
12046
|
+
const namespaces = /* @__PURE__ */ new Set();
|
|
12047
|
+
return {
|
|
12048
|
+
ImportDeclaration(node) {
|
|
12049
|
+
if (node.source.value !== "node:fs" && node.source.value !== "fs") return;
|
|
12050
|
+
const synchronousImports = [];
|
|
12051
|
+
for (const specifier of node.specifiers) {
|
|
12052
|
+
if (specifier.type === import_utils69.AST_NODE_TYPES.ImportNamespaceSpecifier || specifier.type === import_utils69.AST_NODE_TYPES.ImportDefaultSpecifier) {
|
|
12053
|
+
namespaces.add(specifier.local.name);
|
|
12054
|
+
continue;
|
|
12055
|
+
}
|
|
12056
|
+
if (specifier.type === import_utils69.AST_NODE_TYPES.ImportSpecifier && specifier.imported.type === import_utils69.AST_NODE_TYPES.Identifier && specifier.imported.name.endsWith("Sync")) synchronousImports.push(specifier.imported.name);
|
|
12057
|
+
}
|
|
12058
|
+
if (synchronousImports.length > 0) {
|
|
12059
|
+
context.report({
|
|
12060
|
+
node,
|
|
12061
|
+
messageId: "preferAsyncFs",
|
|
12062
|
+
data: { name: synchronousImports.join(", ") }
|
|
12063
|
+
});
|
|
12064
|
+
}
|
|
12065
|
+
},
|
|
12066
|
+
VariableDeclarator(node) {
|
|
12067
|
+
if (node.init === null || !isFsLoader(node.init) && (node.init.type !== import_utils69.AST_NODE_TYPES.Identifier || !namespaces.has(node.init.name)))
|
|
12068
|
+
return;
|
|
12069
|
+
if (node.id.type === import_utils69.AST_NODE_TYPES.Identifier) {
|
|
12070
|
+
namespaces.add(node.id.name);
|
|
12071
|
+
return;
|
|
12072
|
+
}
|
|
12073
|
+
if (node.id.type !== import_utils69.AST_NODE_TYPES.ObjectPattern) return;
|
|
12074
|
+
const synchronousImports = node.id.properties.flatMap((property) => {
|
|
12075
|
+
if (property.type !== import_utils69.AST_NODE_TYPES.Property) return [];
|
|
12076
|
+
const name = propertyName4(property);
|
|
12077
|
+
return name?.endsWith("Sync") === true ? [name] : [];
|
|
12078
|
+
});
|
|
12079
|
+
if (synchronousImports.length > 0) {
|
|
12080
|
+
context.report({
|
|
12081
|
+
node,
|
|
12082
|
+
messageId: "preferAsyncFs",
|
|
12083
|
+
data: { name: synchronousImports.join(", ") }
|
|
12084
|
+
});
|
|
12085
|
+
}
|
|
12086
|
+
},
|
|
12087
|
+
MemberExpression(node) {
|
|
12088
|
+
const name = memberName4(node);
|
|
12089
|
+
if (name?.endsWith("Sync") !== true) return;
|
|
12090
|
+
const object = unwrapAwait2(node.object);
|
|
12091
|
+
if (object.type === import_utils69.AST_NODE_TYPES.Identifier && namespaces.has(object.name) || isFsLoader(object)) {
|
|
12092
|
+
context.report({ node, messageId: "preferAsyncFs", data: { name } });
|
|
12093
|
+
}
|
|
11792
12094
|
}
|
|
11793
12095
|
};
|
|
11794
12096
|
}
|
|
11795
12097
|
});
|
|
11796
12098
|
|
|
11797
12099
|
// src/rules/prefer-non-nullable-collection.ts
|
|
11798
|
-
var
|
|
12100
|
+
var import_utils70 = require("@typescript-eslint/utils");
|
|
11799
12101
|
var PREFER_NON_NULLABLE_COLLECTION_DOCUMENTATION = {
|
|
11800
12102
|
summary: "Suggest non-null arrays only when local control flow proves the nullish state is equivalent to an empty collection.",
|
|
11801
12103
|
rationale: "A redundant nullish collection state spreads defaults and guards through consumers without carrying information.",
|
|
@@ -11808,36 +12110,36 @@ var PREFER_NON_NULLABLE_COLLECTION_DOCUMENTATION = {
|
|
|
11808
12110
|
]
|
|
11809
12111
|
};
|
|
11810
12112
|
var ARRAY_TYPE_NAMES = /* @__PURE__ */ new Set(["Array", "ReadonlyArray"]);
|
|
11811
|
-
function
|
|
12113
|
+
function propertyName5(node) {
|
|
11812
12114
|
const key = node.key;
|
|
11813
12115
|
if (node.computed) return null;
|
|
11814
|
-
if (key.type ===
|
|
11815
|
-
if (key.type ===
|
|
12116
|
+
if (key.type === import_utils70.AST_NODE_TYPES.Identifier) return key.name;
|
|
12117
|
+
if (key.type === import_utils70.AST_NODE_TYPES.Literal && typeof key.value === "string") return key.value;
|
|
11816
12118
|
return null;
|
|
11817
12119
|
}
|
|
11818
12120
|
function isArrayType(node) {
|
|
11819
|
-
if (node.type ===
|
|
11820
|
-
return node.type ===
|
|
12121
|
+
if (node.type === import_utils70.AST_NODE_TYPES.TSArrayType) return true;
|
|
12122
|
+
return node.type === import_utils70.AST_NODE_TYPES.TSTypeReference && node.typeName.type === import_utils70.AST_NODE_TYPES.Identifier && ARRAY_TYPE_NAMES.has(node.typeName.name);
|
|
11821
12123
|
}
|
|
11822
12124
|
function nullableProperty(node) {
|
|
11823
12125
|
if (node.optional) return null;
|
|
11824
|
-
const name =
|
|
12126
|
+
const name = propertyName5(node);
|
|
11825
12127
|
const annotation = node.typeAnnotation?.typeAnnotation;
|
|
11826
|
-
if (name === null || annotation?.type !==
|
|
12128
|
+
if (name === null || annotation?.type !== import_utils70.AST_NODE_TYPES.TSUnionType) return null;
|
|
11827
12129
|
const concrete = annotation.types.filter(
|
|
11828
|
-
(member) => member.type !==
|
|
12130
|
+
(member) => member.type !== import_utils70.AST_NODE_TYPES.TSNullKeyword && member.type !== import_utils70.AST_NODE_TYPES.TSUndefinedKeyword
|
|
11829
12131
|
);
|
|
11830
12132
|
if (concrete.length === 0 || !concrete.every(isArrayType)) return null;
|
|
11831
|
-
const acceptsNull = annotation.types.some((member) => member.type ===
|
|
12133
|
+
const acceptsNull = annotation.types.some((member) => member.type === import_utils70.AST_NODE_TYPES.TSNullKeyword);
|
|
11832
12134
|
const acceptsUndefined = annotation.types.some(
|
|
11833
|
-
(member) => member.type ===
|
|
12135
|
+
(member) => member.type === import_utils70.AST_NODE_TYPES.TSUndefinedKeyword
|
|
11834
12136
|
);
|
|
11835
12137
|
if (!acceptsNull && !acceptsUndefined) return null;
|
|
11836
12138
|
return { name, node, acceptsNull, acceptsUndefined };
|
|
11837
12139
|
}
|
|
11838
12140
|
function shapeProperties(members) {
|
|
11839
12141
|
return members.flatMap((member) => {
|
|
11840
|
-
if (member.type !==
|
|
12142
|
+
if (member.type !== import_utils70.AST_NODE_TYPES.TSPropertySignature) return [];
|
|
11841
12143
|
const property = nullableProperty(member);
|
|
11842
12144
|
return property === null ? [] : [property];
|
|
11843
12145
|
});
|
|
@@ -11845,14 +12147,14 @@ function shapeProperties(members) {
|
|
|
11845
12147
|
function typeIndex(program) {
|
|
11846
12148
|
const index = /* @__PURE__ */ new Map();
|
|
11847
12149
|
for (const statement of program.body) {
|
|
11848
|
-
const exported = statement.type ===
|
|
12150
|
+
const exported = statement.type === import_utils70.AST_NODE_TYPES.ExportNamedDeclaration;
|
|
11849
12151
|
const declaration = exported ? statement.declaration : statement;
|
|
11850
|
-
if (declaration?.type ===
|
|
12152
|
+
if (declaration?.type === import_utils70.AST_NODE_TYPES.TSInterfaceDeclaration) {
|
|
11851
12153
|
index.set(declaration.id.name, {
|
|
11852
12154
|
exported,
|
|
11853
12155
|
properties: shapeProperties(declaration.body.body)
|
|
11854
12156
|
});
|
|
11855
|
-
} else if (declaration?.type ===
|
|
12157
|
+
} else if (declaration?.type === import_utils70.AST_NODE_TYPES.TSTypeAliasDeclaration && declaration.typeAnnotation.type === import_utils70.AST_NODE_TYPES.TSTypeLiteral) {
|
|
11856
12158
|
index.set(declaration.id.name, {
|
|
11857
12159
|
exported,
|
|
11858
12160
|
properties: shapeProperties(declaration.typeAnnotation.members)
|
|
@@ -11862,42 +12164,42 @@ function typeIndex(program) {
|
|
|
11862
12164
|
return index;
|
|
11863
12165
|
}
|
|
11864
12166
|
function emptyArray(node) {
|
|
11865
|
-
return node.type ===
|
|
12167
|
+
return node.type === import_utils70.AST_NODE_TYPES.ArrayExpression && node.elements.length === 0;
|
|
11866
12168
|
}
|
|
11867
12169
|
function sameAccess(node, access) {
|
|
11868
12170
|
if (access.kind === "identifier") {
|
|
11869
|
-
return node.type ===
|
|
12171
|
+
return node.type === import_utils70.AST_NODE_TYPES.Identifier && node.name === access.name;
|
|
11870
12172
|
}
|
|
11871
|
-
return node.type ===
|
|
12173
|
+
return node.type === import_utils70.AST_NODE_TYPES.MemberExpression && !node.computed && node.object.type === import_utils70.AST_NODE_TYPES.Identifier && node.object.name === access.object && node.property.type === import_utils70.AST_NODE_TYPES.Identifier && node.property.name === access.property;
|
|
11872
12174
|
}
|
|
11873
12175
|
function isNullGuard(node, access) {
|
|
11874
|
-
if (node.type ===
|
|
11875
|
-
if (node.type !==
|
|
12176
|
+
if (node.type === import_utils70.AST_NODE_TYPES.UnaryExpression && node.operator === "!" && (sameAccess(node.argument, access) || optionalMemberLengthOf(node.argument, access))) return true;
|
|
12177
|
+
if (node.type !== import_utils70.AST_NODE_TYPES.BinaryExpression || !["==", "==="].includes(node.operator)) {
|
|
11876
12178
|
return false;
|
|
11877
12179
|
}
|
|
11878
|
-
const nullish = (value) => value.type ===
|
|
12180
|
+
const nullish = (value) => value.type === import_utils70.AST_NODE_TYPES.Literal && value.value === null || value.type === import_utils70.AST_NODE_TYPES.Identifier && value.name === "undefined";
|
|
11879
12181
|
return sameAccess(node.left, access) && nullish(node.right) || sameAccess(node.right, access) && nullish(node.left);
|
|
11880
12182
|
}
|
|
11881
12183
|
function isEmptyGuard(node, access) {
|
|
11882
|
-
if (node.type ===
|
|
11883
|
-
if (node.type !==
|
|
12184
|
+
if (node.type === import_utils70.AST_NODE_TYPES.UnaryExpression && node.operator === "!" && memberLengthOf(node.argument, access)) return true;
|
|
12185
|
+
if (node.type !== import_utils70.AST_NODE_TYPES.BinaryExpression || !["==", "===", "<="].includes(node.operator)) {
|
|
11884
12186
|
return false;
|
|
11885
12187
|
}
|
|
11886
|
-
const zero = (value) => value.type ===
|
|
12188
|
+
const zero = (value) => value.type === import_utils70.AST_NODE_TYPES.Literal && value.value === 0;
|
|
11887
12189
|
return memberLengthOf(node.left, access) && zero(node.right) || memberLengthOf(node.right, access) && zero(node.left);
|
|
11888
12190
|
}
|
|
11889
12191
|
function memberLengthOf(node, access) {
|
|
11890
|
-
const target = node.type ===
|
|
11891
|
-
return target.type ===
|
|
12192
|
+
const target = node.type === import_utils70.AST_NODE_TYPES.ChainExpression ? node.expression : node;
|
|
12193
|
+
return target.type === import_utils70.AST_NODE_TYPES.MemberExpression && !target.computed && target.property.type === import_utils70.AST_NODE_TYPES.Identifier && target.property.name === "length" && sameAccess(target.object, access);
|
|
11892
12194
|
}
|
|
11893
12195
|
function optionalMemberLengthOf(node, access) {
|
|
11894
|
-
return node.type ===
|
|
12196
|
+
return node.type === import_utils70.AST_NODE_TYPES.ChainExpression && node.expression.type === import_utils70.AST_NODE_TYPES.MemberExpression && node.expression.optional && memberLengthOf(node, access);
|
|
11895
12197
|
}
|
|
11896
12198
|
function hasEquivalentLeadingGuard(fn, access, visitorKeys) {
|
|
11897
|
-
if (fn.body.type !==
|
|
12199
|
+
if (fn.body.type !== import_utils70.AST_NODE_TYPES.BlockStatement) return false;
|
|
11898
12200
|
const first = fn.body.body[0];
|
|
11899
|
-
if (first?.type !==
|
|
11900
|
-
const terminating = first.consequent.type ===
|
|
12201
|
+
if (first?.type !== import_utils70.AST_NODE_TYPES.IfStatement) return false;
|
|
12202
|
+
const terminating = first.consequent.type === import_utils70.AST_NODE_TYPES.ReturnStatement || first.consequent.type === import_utils70.AST_NODE_TYPES.ThrowStatement || first.consequent.type === import_utils70.AST_NODE_TYPES.BlockStatement && first.consequent.body.length === 1 && (first.consequent.body[0]?.type === import_utils70.AST_NODE_TYPES.ReturnStatement || first.consequent.body[0]?.type === import_utils70.AST_NODE_TYPES.ThrowStatement);
|
|
11901
12203
|
if (!terminating) return false;
|
|
11902
12204
|
if (contains(first.consequent, visitorKeys, (node) => sameAccess(node, access))) return false;
|
|
11903
12205
|
return contains(first.test, visitorKeys, (node) => isNullGuard(node, access)) && contains(first.test, visitorKeys, (node) => isEmptyGuard(node, access));
|
|
@@ -11915,29 +12217,29 @@ function contains(node, visitorKeys, predicate) {
|
|
|
11915
12217
|
function belongsToFunction(node, fn) {
|
|
11916
12218
|
let current = node;
|
|
11917
12219
|
while (current !== void 0 && current !== fn) {
|
|
11918
|
-
if (current !== node && (current.type ===
|
|
12220
|
+
if (current !== node && (current.type === import_utils70.AST_NODE_TYPES.ArrowFunctionExpression || current.type === import_utils70.AST_NODE_TYPES.FunctionDeclaration || current.type === import_utils70.AST_NODE_TYPES.FunctionExpression)) return false;
|
|
11919
12221
|
current = current.parent;
|
|
11920
12222
|
}
|
|
11921
12223
|
return current === fn;
|
|
11922
12224
|
}
|
|
11923
12225
|
function directlyCoalesced(node) {
|
|
11924
12226
|
const parent = node.parent;
|
|
11925
|
-
return parent?.type ===
|
|
12227
|
+
return parent?.type === import_utils70.AST_NODE_TYPES.LogicalExpression && parent.left === node && (parent.operator === "??" || parent.operator === "||") && emptyArray(parent.right);
|
|
11926
12228
|
}
|
|
11927
12229
|
function identifierIsOnlyCoalesced(context, binding, fn) {
|
|
11928
|
-
const variable =
|
|
12230
|
+
const variable = import_utils70.ASTUtils.findVariable(context.sourceCode.getScope(binding), binding.name);
|
|
11929
12231
|
if (variable === null || variable.references.length === 0) return false;
|
|
11930
12232
|
return variable.references.every(
|
|
11931
12233
|
(reference) => belongsToFunction(reference.identifier, fn) && directlyCoalesced(reference.identifier)
|
|
11932
12234
|
);
|
|
11933
12235
|
}
|
|
11934
12236
|
function memberIsOnlyCoalesced(context, object, property, fn) {
|
|
11935
|
-
const variable =
|
|
12237
|
+
const variable = import_utils70.ASTUtils.findVariable(context.sourceCode.getScope(object), object.name);
|
|
11936
12238
|
if (variable === null) return false;
|
|
11937
12239
|
const accesses = variable.references.flatMap((reference) => {
|
|
11938
12240
|
if (!belongsToFunction(reference.identifier, fn)) return [null];
|
|
11939
12241
|
const parent = reference.identifier.parent;
|
|
11940
|
-
if (parent?.type ===
|
|
12242
|
+
if (parent?.type === import_utils70.AST_NODE_TYPES.MemberExpression && !parent.computed && parent.object === reference.identifier && parent.property.type === import_utils70.AST_NODE_TYPES.Identifier && parent.property.name === property) return [parent];
|
|
11941
12243
|
return [];
|
|
11942
12244
|
});
|
|
11943
12245
|
return accesses.length > 0 && accesses.every((access) => access !== null && directlyCoalesced(access));
|
|
@@ -11963,8 +12265,8 @@ var prefer_non_nullable_collection_default = createRule({
|
|
|
11963
12265
|
let shapes = /* @__PURE__ */ new Map();
|
|
11964
12266
|
const evidence = /* @__PURE__ */ new Map();
|
|
11965
12267
|
function propertiesFor(annotation) {
|
|
11966
|
-
if (annotation?.type ===
|
|
11967
|
-
if (annotation?.type ===
|
|
12268
|
+
if (annotation?.type === import_utils70.AST_NODE_TYPES.TSTypeLiteral) return shapeProperties(annotation.members);
|
|
12269
|
+
if (annotation?.type === import_utils70.AST_NODE_TYPES.TSTypeReference && annotation.typeName.type === import_utils70.AST_NODE_TYPES.Identifier) {
|
|
11968
12270
|
const shape = shapes.get(annotation.typeName.name);
|
|
11969
12271
|
return shape?.exported === false ? shape.properties : [];
|
|
11970
12272
|
}
|
|
@@ -11977,21 +12279,21 @@ var prefer_non_nullable_collection_default = createRule({
|
|
|
11977
12279
|
}
|
|
11978
12280
|
function checkFunction(fn) {
|
|
11979
12281
|
for (const rawParameter of fn.params) {
|
|
11980
|
-
const parameter = rawParameter.type ===
|
|
11981
|
-
if (parameter.type ===
|
|
12282
|
+
const parameter = rawParameter.type === import_utils70.AST_NODE_TYPES.AssignmentPattern ? rawParameter.left : rawParameter;
|
|
12283
|
+
if (parameter.type === import_utils70.AST_NODE_TYPES.ObjectPattern) {
|
|
11982
12284
|
const properties2 = propertiesFor(parameter.typeAnnotation?.typeAnnotation);
|
|
11983
12285
|
for (const property of properties2) {
|
|
11984
12286
|
const bindingProperty = parameter.properties.find(
|
|
11985
|
-
(entry) => entry.type ===
|
|
12287
|
+
(entry) => entry.type === import_utils70.AST_NODE_TYPES.Property && !entry.computed && entry.key.type === import_utils70.AST_NODE_TYPES.Identifier && entry.key.name === property.name
|
|
11986
12288
|
);
|
|
11987
12289
|
if (bindingProperty === void 0) continue;
|
|
11988
12290
|
const value = bindingProperty.value;
|
|
11989
|
-
const binding = value.type ===
|
|
11990
|
-
if (binding.type !==
|
|
12291
|
+
const binding = value.type === import_utils70.AST_NODE_TYPES.AssignmentPattern ? value.left : value;
|
|
12292
|
+
if (binding.type !== import_utils70.AST_NODE_TYPES.Identifier) {
|
|
11991
12293
|
record(property, false);
|
|
11992
12294
|
continue;
|
|
11993
12295
|
}
|
|
11994
|
-
if (value.type ===
|
|
12296
|
+
if (value.type === import_utils70.AST_NODE_TYPES.AssignmentPattern && emptyArray(value.right) && property.acceptsUndefined && !property.acceptsNull) {
|
|
11995
12297
|
record(property, true);
|
|
11996
12298
|
continue;
|
|
11997
12299
|
}
|
|
@@ -12003,7 +12305,7 @@ var prefer_non_nullable_collection_default = createRule({
|
|
|
12003
12305
|
}
|
|
12004
12306
|
continue;
|
|
12005
12307
|
}
|
|
12006
|
-
if (parameter.type !==
|
|
12308
|
+
if (parameter.type !== import_utils70.AST_NODE_TYPES.Identifier) continue;
|
|
12007
12309
|
const properties = propertiesFor(parameter.typeAnnotation?.typeAnnotation);
|
|
12008
12310
|
for (const property of properties) {
|
|
12009
12311
|
const access = {
|
|
@@ -12031,7 +12333,7 @@ var prefer_non_nullable_collection_default = createRule({
|
|
|
12031
12333
|
context.report({
|
|
12032
12334
|
node,
|
|
12033
12335
|
messageId: "preferNonNullableCollection",
|
|
12034
|
-
data: { name:
|
|
12336
|
+
data: { name: propertyName5(node) ?? "collection" }
|
|
12035
12337
|
});
|
|
12036
12338
|
}
|
|
12037
12339
|
}
|
|
@@ -12040,7 +12342,7 @@ var prefer_non_nullable_collection_default = createRule({
|
|
|
12040
12342
|
});
|
|
12041
12343
|
|
|
12042
12344
|
// src/rules/prefer-nullish-filter-predicate.ts
|
|
12043
|
-
var
|
|
12345
|
+
var import_utils71 = require("@typescript-eslint/utils");
|
|
12044
12346
|
var import_typescript = __toESM(require("typescript"), 1);
|
|
12045
12347
|
var PREFER_NULLISH_FILTER_PREDICATE_DOCUMENTATION = {
|
|
12046
12348
|
summary: "Prefer an explicit nullish predicate when `filter(Boolean)` removes only nullish values but does not narrow the result type.",
|
|
@@ -12084,7 +12386,7 @@ var PREFER_NULLISH_FILTER_PREDICATE_DOCUMENTATION = {
|
|
|
12084
12386
|
]
|
|
12085
12387
|
};
|
|
12086
12388
|
function isUnshadowedBoolean(node, context) {
|
|
12087
|
-
const variable =
|
|
12389
|
+
const variable = import_utils71.ASTUtils.findVariable(context.sourceCode.getScope(node), node.name);
|
|
12088
12390
|
return variable === null || variable.defs.length === 0;
|
|
12089
12391
|
}
|
|
12090
12392
|
function isBuiltinArrayFilter(node, services) {
|
|
@@ -12143,7 +12445,7 @@ function isProvablyTruthy(type, checker) {
|
|
|
12143
12445
|
}
|
|
12144
12446
|
function availableParameterName(node, context) {
|
|
12145
12447
|
for (const name of ["value", "item", "element", "candidate"]) {
|
|
12146
|
-
if (
|
|
12448
|
+
if (import_utils71.ASTUtils.findVariable(context.sourceCode.getScope(node), name) === null) return name;
|
|
12147
12449
|
}
|
|
12148
12450
|
return null;
|
|
12149
12451
|
}
|
|
@@ -12165,7 +12467,7 @@ var prefer_nullish_filter_predicate_default = createRule({
|
|
|
12165
12467
|
if (isGeneratedFile(context.filename, context.sourceCode.text)) return {};
|
|
12166
12468
|
let services;
|
|
12167
12469
|
try {
|
|
12168
|
-
services =
|
|
12470
|
+
services = import_utils71.ESLintUtils.getParserServices(context);
|
|
12169
12471
|
} catch {
|
|
12170
12472
|
services = null;
|
|
12171
12473
|
}
|
|
@@ -12174,7 +12476,7 @@ var prefer_nullish_filter_predicate_default = createRule({
|
|
|
12174
12476
|
CallExpression(node) {
|
|
12175
12477
|
const callee = node.callee;
|
|
12176
12478
|
const callback = node.arguments[0];
|
|
12177
|
-
if (node.arguments.length !== 1 || callback?.type !==
|
|
12479
|
+
if (node.arguments.length !== 1 || callback?.type !== import_utils71.AST_NODE_TYPES.Identifier || callback.name !== "Boolean" || callee.type !== import_utils71.AST_NODE_TYPES.MemberExpression || callee.computed || callee.property.type !== import_utils71.AST_NODE_TYPES.Identifier || callee.property.name !== "filter" || !isUnshadowedBoolean(callback, context) || !isBuiltinArrayFilter(callee, services)) return;
|
|
12178
12480
|
const elementType = arrayElementType(callee.object, services);
|
|
12179
12481
|
const checker = services.program.getTypeChecker();
|
|
12180
12482
|
if (elementType === null || !isNullishPlusTruthy(elementType, checker)) return;
|
|
@@ -12196,7 +12498,7 @@ var prefer_nullish_filter_predicate_default = createRule({
|
|
|
12196
12498
|
});
|
|
12197
12499
|
|
|
12198
12500
|
// src/rules/prefer-await-in-async-return.ts
|
|
12199
|
-
var
|
|
12501
|
+
var import_utils72 = require("@typescript-eslint/utils");
|
|
12200
12502
|
var ts4 = __toESM(require("typescript"), 1);
|
|
12201
12503
|
var PREFER_AWAIT_IN_ASYNC_RETURN_DOCUMENTATION = {
|
|
12202
12504
|
summary: "Prefer explicit `await` when an async function directly returns one typed Promise `.then` transform.",
|
|
@@ -12238,10 +12540,10 @@ var PREFER_AWAIT_IN_ASYNC_RETURN_DOCUMENTATION = {
|
|
|
12238
12540
|
};
|
|
12239
12541
|
function directAsyncReturnOwner(node) {
|
|
12240
12542
|
const parent = node.parent;
|
|
12241
|
-
if (parent.type ===
|
|
12543
|
+
if (parent.type === import_utils72.AST_NODE_TYPES.ArrowFunctionExpression && parent.body === node) {
|
|
12242
12544
|
return parent.async && !parent.generator ? parent : null;
|
|
12243
12545
|
}
|
|
12244
|
-
if (parent.type !==
|
|
12546
|
+
if (parent.type !== import_utils72.AST_NODE_TYPES.ReturnStatement || parent.argument !== node) {
|
|
12245
12547
|
return null;
|
|
12246
12548
|
}
|
|
12247
12549
|
let owner = parent.parent;
|
|
@@ -12251,15 +12553,15 @@ function directAsyncReturnOwner(node) {
|
|
|
12251
12553
|
return owner !== void 0 && owner.async && !owner.generator ? owner : null;
|
|
12252
12554
|
}
|
|
12253
12555
|
function isRuntimeFunction(node) {
|
|
12254
|
-
return node.type ===
|
|
12556
|
+
return node.type === import_utils72.AST_NODE_TYPES.ArrowFunctionExpression || node.type === import_utils72.AST_NODE_TYPES.FunctionDeclaration || node.type === import_utils72.AST_NODE_TYPES.FunctionExpression;
|
|
12255
12557
|
}
|
|
12256
12558
|
function promiseThenReceiver(node) {
|
|
12257
12559
|
const callee = node.callee;
|
|
12258
|
-
if (callee.type !==
|
|
12560
|
+
if (callee.type !== import_utils72.AST_NODE_TYPES.MemberExpression || callee.computed || callee.optional || callee.property.type !== import_utils72.AST_NODE_TYPES.Identifier || callee.property.name !== "then" || node.optional || node.arguments.length !== 1) {
|
|
12259
12561
|
return null;
|
|
12260
12562
|
}
|
|
12261
12563
|
const callback = node.arguments[0];
|
|
12262
|
-
if (callback === void 0 || callback.type !==
|
|
12564
|
+
if (callback === void 0 || callback.type !== import_utils72.AST_NODE_TYPES.ArrowFunctionExpression && callback.type !== import_utils72.AST_NODE_TYPES.FunctionExpression) {
|
|
12263
12565
|
return null;
|
|
12264
12566
|
}
|
|
12265
12567
|
return callee.object;
|
|
@@ -12300,32 +12602,32 @@ var prefer_await_in_async_return_default = createRule({
|
|
|
12300
12602
|
create(context) {
|
|
12301
12603
|
let services;
|
|
12302
12604
|
try {
|
|
12303
|
-
services =
|
|
12605
|
+
services = import_utils72.ESLintUtils.getParserServices(context);
|
|
12304
12606
|
} catch {
|
|
12305
12607
|
services = null;
|
|
12306
12608
|
}
|
|
12307
12609
|
if (services === null) return {};
|
|
12308
12610
|
const frameworkLoaders = /* @__PURE__ */ new Set();
|
|
12309
12611
|
const rememberFrameworkLoader = (identifier) => {
|
|
12310
|
-
const variable =
|
|
12612
|
+
const variable = import_utils72.ASTUtils.findVariable(context.sourceCode.getScope(identifier), identifier.name);
|
|
12311
12613
|
if (variable !== null) frameworkLoaders.add(variable);
|
|
12312
12614
|
};
|
|
12313
12615
|
const isFrameworkLoaderCallback = (owner) => {
|
|
12314
12616
|
const parent = owner.parent;
|
|
12315
|
-
if (parent.type !==
|
|
12316
|
-
const variable =
|
|
12617
|
+
if (parent.type !== import_utils72.AST_NODE_TYPES.CallExpression || parent.arguments[0] !== owner || parent.callee.type !== import_utils72.AST_NODE_TYPES.Identifier) return false;
|
|
12618
|
+
const variable = import_utils72.ASTUtils.findVariable(context.sourceCode.getScope(parent.callee), parent.callee.name);
|
|
12317
12619
|
return variable !== null && frameworkLoaders.has(variable);
|
|
12318
12620
|
};
|
|
12319
12621
|
return {
|
|
12320
12622
|
ImportDeclaration(node) {
|
|
12321
12623
|
if (node.source.value === "react") {
|
|
12322
12624
|
for (const specifier of node.specifiers) {
|
|
12323
|
-
if (specifier.type ===
|
|
12625
|
+
if (specifier.type === import_utils72.AST_NODE_TYPES.ImportSpecifier && (specifier.imported.type === import_utils72.AST_NODE_TYPES.Identifier ? specifier.imported.name : specifier.imported.value) === "lazy") rememberFrameworkLoader(specifier.local);
|
|
12324
12626
|
}
|
|
12325
12627
|
}
|
|
12326
12628
|
if (node.source.value === "next/dynamic") {
|
|
12327
12629
|
for (const specifier of node.specifiers) {
|
|
12328
|
-
if (specifier.type ===
|
|
12630
|
+
if (specifier.type === import_utils72.AST_NODE_TYPES.ImportDefaultSpecifier) rememberFrameworkLoader(specifier.local);
|
|
12329
12631
|
}
|
|
12330
12632
|
}
|
|
12331
12633
|
},
|
|
@@ -12343,7 +12645,7 @@ var prefer_await_in_async_return_default = createRule({
|
|
|
12343
12645
|
});
|
|
12344
12646
|
|
|
12345
12647
|
// src/rules/prefer-schema-for-api-payload.ts
|
|
12346
|
-
var
|
|
12648
|
+
var import_utils73 = require("@typescript-eslint/utils");
|
|
12347
12649
|
var PREFER_SCHEMA_FOR_API_PAYLOAD_DOCUMENTATION = {
|
|
12348
12650
|
summary: "Require Zod (or similar) schema validation on `response.json()` / `JSON.parse()` results before property access.",
|
|
12349
12651
|
rationale: "External JSON is untrusted at runtime even when its expected TypeScript shape is known statically.",
|
|
@@ -12355,12 +12657,12 @@ var PREFER_SCHEMA_FOR_API_PAYLOAD_DOCUMENTATION = {
|
|
|
12355
12657
|
{ 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 }
|
|
12356
12658
|
]
|
|
12357
12659
|
};
|
|
12358
|
-
var
|
|
12660
|
+
var unwrap5 = (node) => {
|
|
12359
12661
|
let current = node;
|
|
12360
12662
|
while (current !== null && current !== void 0) {
|
|
12361
|
-
if (current.type ===
|
|
12663
|
+
if (current.type === import_utils73.AST_NODE_TYPES.TSAsExpression || current.type === import_utils73.AST_NODE_TYPES.TSTypeAssertion || current.type === import_utils73.AST_NODE_TYPES.TSNonNullExpression || current.type === import_utils73.AST_NODE_TYPES.TSSatisfiesExpression) {
|
|
12362
12664
|
current = current.expression;
|
|
12363
|
-
} else if (current.type ===
|
|
12665
|
+
} else if (current.type === import_utils73.AST_NODE_TYPES.ChainExpression) {
|
|
12364
12666
|
current = current.expression;
|
|
12365
12667
|
} else {
|
|
12366
12668
|
break;
|
|
@@ -12374,24 +12676,24 @@ var PROMISE_CHAIN_METHODS = /* @__PURE__ */ new Set([
|
|
|
12374
12676
|
"finally"
|
|
12375
12677
|
]);
|
|
12376
12678
|
var isSchemaParseReference = (node) => {
|
|
12377
|
-
const inner =
|
|
12378
|
-
return inner !== null && inner.type ===
|
|
12679
|
+
const inner = unwrap5(node);
|
|
12680
|
+
return inner !== null && inner.type === import_utils73.AST_NODE_TYPES.MemberExpression && !inner.computed && inner.property.type === import_utils73.AST_NODE_TYPES.Identifier && (inner.property.name === "parse" || inner.property.name === "safeParse");
|
|
12379
12681
|
};
|
|
12380
12682
|
var isRawPayloadSource = (node, isKnownLocalText) => {
|
|
12381
|
-
let current =
|
|
12683
|
+
let current = unwrap5(node);
|
|
12382
12684
|
if (current === null) return false;
|
|
12383
|
-
if (current.type ===
|
|
12384
|
-
current =
|
|
12685
|
+
if (current.type === import_utils73.AST_NODE_TYPES.AwaitExpression) {
|
|
12686
|
+
current = unwrap5(current.argument);
|
|
12385
12687
|
}
|
|
12386
|
-
if (current === null || current.type !==
|
|
12688
|
+
if (current === null || current.type !== import_utils73.AST_NODE_TYPES.CallExpression) {
|
|
12387
12689
|
return false;
|
|
12388
12690
|
}
|
|
12389
|
-
const callee =
|
|
12390
|
-
if (callee === null || callee.type !==
|
|
12691
|
+
const callee = unwrap5(current.callee);
|
|
12692
|
+
if (callee === null || callee.type !== import_utils73.AST_NODE_TYPES.MemberExpression) {
|
|
12391
12693
|
return false;
|
|
12392
12694
|
}
|
|
12393
|
-
const property =
|
|
12394
|
-
if (property === null || property.type !==
|
|
12695
|
+
const property = unwrap5(callee.property);
|
|
12696
|
+
if (property === null || property.type !== import_utils73.AST_NODE_TYPES.Identifier) {
|
|
12395
12697
|
return false;
|
|
12396
12698
|
}
|
|
12397
12699
|
if (property.name === "json") {
|
|
@@ -12400,18 +12702,18 @@ var isRawPayloadSource = (node, isKnownLocalText) => {
|
|
|
12400
12702
|
if (PROMISE_CHAIN_METHODS.has(property.name)) {
|
|
12401
12703
|
return !current.arguments.some(isSchemaParseReference) && isRawPayloadSource(callee.object);
|
|
12402
12704
|
}
|
|
12403
|
-
const object =
|
|
12404
|
-
return property.name === "parse" && object !== null && object.type ===
|
|
12705
|
+
const object = unwrap5(callee.object);
|
|
12706
|
+
return property.name === "parse" && object !== null && object.type === import_utils73.AST_NODE_TYPES.Identifier && object.name === "JSON" && !isLocalFileRead(current.arguments[0]) && isKnownLocalText?.(current.arguments[0]) !== true;
|
|
12405
12707
|
};
|
|
12406
12708
|
var FILE_READ_RE = /^(readFile|readFileSync|readJson|readJsonSync|readJSON)$/;
|
|
12407
12709
|
var isDirectLocalFileRead = (node) => {
|
|
12408
|
-
let current =
|
|
12409
|
-
if (current?.type ===
|
|
12410
|
-
current =
|
|
12710
|
+
let current = unwrap5(node);
|
|
12711
|
+
if (current?.type === import_utils73.AST_NODE_TYPES.AwaitExpression) {
|
|
12712
|
+
current = unwrap5(current.argument);
|
|
12411
12713
|
}
|
|
12412
|
-
if (current?.type !==
|
|
12413
|
-
const callee =
|
|
12414
|
-
const name = callee?.type ===
|
|
12714
|
+
if (current?.type !== import_utils73.AST_NODE_TYPES.CallExpression) return false;
|
|
12715
|
+
const callee = unwrap5(current.callee);
|
|
12716
|
+
const name = callee?.type === import_utils73.AST_NODE_TYPES.Identifier ? callee.name : callee?.type === import_utils73.AST_NODE_TYPES.MemberExpression && !callee.computed && callee.property.type === import_utils73.AST_NODE_TYPES.Identifier ? callee.property.name : null;
|
|
12415
12717
|
return name !== null && FILE_READ_RE.test(name);
|
|
12416
12718
|
};
|
|
12417
12719
|
var isLocalFileRead = (node) => {
|
|
@@ -12438,15 +12740,15 @@ var isLocalFileRead = (node) => {
|
|
|
12438
12740
|
var ASSERTION_CALLEE_RE = /^(expect|assert|should|invariant)$/;
|
|
12439
12741
|
var isInsideAssertion = (node) => {
|
|
12440
12742
|
for (let current = node.parent; current !== void 0 && current !== null; current = current.parent) {
|
|
12441
|
-
if (current.type !==
|
|
12743
|
+
if (current.type !== import_utils73.AST_NODE_TYPES.CallExpression) continue;
|
|
12442
12744
|
let callee = current.callee;
|
|
12443
|
-
while (callee.type ===
|
|
12745
|
+
while (callee.type === import_utils73.AST_NODE_TYPES.MemberExpression) {
|
|
12444
12746
|
callee = callee.object;
|
|
12445
12747
|
}
|
|
12446
|
-
if (callee.type ===
|
|
12748
|
+
if (callee.type === import_utils73.AST_NODE_TYPES.CallExpression) {
|
|
12447
12749
|
callee = callee.callee;
|
|
12448
12750
|
}
|
|
12449
|
-
if (callee.type ===
|
|
12751
|
+
if (callee.type === import_utils73.AST_NODE_TYPES.Identifier && ASSERTION_CALLEE_RE.test(callee.name)) {
|
|
12450
12752
|
return true;
|
|
12451
12753
|
}
|
|
12452
12754
|
}
|
|
@@ -12465,22 +12767,22 @@ var GUARD_NAME_RE = /^(?:is|validate|parse|assert|decode|coerce)[A-Z]/;
|
|
|
12465
12767
|
var isValidationRead = (node) => {
|
|
12466
12768
|
let current = node;
|
|
12467
12769
|
let parent = current.parent;
|
|
12468
|
-
while (parent !== null && parent !== void 0 && (parent.type ===
|
|
12770
|
+
while (parent !== null && parent !== void 0 && (parent.type === import_utils73.AST_NODE_TYPES.TSAsExpression || parent.type === import_utils73.AST_NODE_TYPES.TSTypeAssertion || parent.type === import_utils73.AST_NODE_TYPES.TSNonNullExpression || parent.type === import_utils73.AST_NODE_TYPES.TSSatisfiesExpression || parent.type === import_utils73.AST_NODE_TYPES.ChainExpression)) {
|
|
12469
12771
|
current = parent;
|
|
12470
12772
|
parent = parent.parent;
|
|
12471
12773
|
}
|
|
12472
12774
|
if (parent === null || parent === void 0) return false;
|
|
12473
|
-
if (parent.type ===
|
|
12775
|
+
if (parent.type === import_utils73.AST_NODE_TYPES.UnaryExpression && parent.operator === "typeof" && parent.argument === current) {
|
|
12474
12776
|
return true;
|
|
12475
12777
|
}
|
|
12476
|
-
if (parent.type !==
|
|
12778
|
+
if (parent.type !== import_utils73.AST_NODE_TYPES.CallExpression || !parent.arguments.some((arg) => arg === current)) {
|
|
12477
12779
|
return false;
|
|
12478
12780
|
}
|
|
12479
12781
|
const callee = parent.callee;
|
|
12480
|
-
if (callee.type ===
|
|
12782
|
+
if (callee.type === import_utils73.AST_NODE_TYPES.MemberExpression && !callee.computed && callee.object.type === import_utils73.AST_NODE_TYPES.Identifier && callee.object.name === "Array" && callee.property.type === import_utils73.AST_NODE_TYPES.Identifier && callee.property.name === "isArray") {
|
|
12481
12783
|
return parent.arguments.length === 1;
|
|
12482
12784
|
}
|
|
12483
|
-
return callee.type ===
|
|
12785
|
+
return callee.type === import_utils73.AST_NODE_TYPES.Identifier && GUARD_NAME_RE.test(callee.name);
|
|
12484
12786
|
};
|
|
12485
12787
|
var PRIMITIVE_TYPEOF_RESULTS = /* @__PURE__ */ new Set([
|
|
12486
12788
|
"bigint",
|
|
@@ -12491,13 +12793,13 @@ var PRIMITIVE_TYPEOF_RESULTS = /* @__PURE__ */ new Set([
|
|
|
12491
12793
|
"undefined"
|
|
12492
12794
|
]);
|
|
12493
12795
|
var bindingValidationPolarity = (test, bindingName) => {
|
|
12494
|
-
if (test.type ===
|
|
12796
|
+
if (test.type === import_utils73.AST_NODE_TYPES.UnaryExpression && test.operator === "!") {
|
|
12495
12797
|
const inner = bindingValidationPolarity(test.argument, bindingName);
|
|
12496
12798
|
return inner === "valid-when-true" ? "valid-when-false" : inner === "valid-when-false" ? "valid-when-true" : null;
|
|
12497
12799
|
}
|
|
12498
|
-
if (test.type ===
|
|
12499
|
-
const typeofName = (node) => node.type ===
|
|
12500
|
-
const literalType = (node) => node.type ===
|
|
12800
|
+
if (test.type === import_utils73.AST_NODE_TYPES.BinaryExpression) {
|
|
12801
|
+
const typeofName = (node) => node.type === import_utils73.AST_NODE_TYPES.UnaryExpression && node.operator === "typeof" && node.argument.type === import_utils73.AST_NODE_TYPES.Identifier ? node.argument.name : null;
|
|
12802
|
+
const literalType = (node) => node.type === import_utils73.AST_NODE_TYPES.Literal && typeof node.value === "string" && PRIMITIVE_TYPEOF_RESULTS.has(node.value) ? node.value : null;
|
|
12501
12803
|
const matches = typeofName(test.left) === bindingName && literalType(test.right) !== null || typeofName(test.right) === bindingName && literalType(test.left) !== null;
|
|
12502
12804
|
if (!matches) return null;
|
|
12503
12805
|
if (test.operator === "===" || test.operator === "==") {
|
|
@@ -12505,9 +12807,9 @@ var bindingValidationPolarity = (test, bindingName) => {
|
|
|
12505
12807
|
}
|
|
12506
12808
|
return test.operator === "!==" || test.operator === "!=" ? "valid-when-false" : null;
|
|
12507
12809
|
}
|
|
12508
|
-
return test.type ===
|
|
12810
|
+
return test.type === import_utils73.AST_NODE_TYPES.CallExpression && test.arguments.length === 1 && test.arguments[0]?.type === import_utils73.AST_NODE_TYPES.Identifier && test.arguments[0].name === bindingName && test.callee.type === import_utils73.AST_NODE_TYPES.MemberExpression && !test.callee.computed && test.callee.object.type === import_utils73.AST_NODE_TYPES.Identifier && test.callee.object.name === "Array" && test.callee.property.type === import_utils73.AST_NODE_TYPES.Identifier && test.callee.property.name === "isArray" ? "valid-when-true" : null;
|
|
12509
12811
|
};
|
|
12510
|
-
var plainMemberAccess = (node) => node.type ===
|
|
12812
|
+
var plainMemberAccess = (node) => node.type === import_utils73.AST_NODE_TYPES.MemberExpression && !node.computed && node.object.type === import_utils73.AST_NODE_TYPES.Identifier && node.property.type === import_utils73.AST_NODE_TYPES.Identifier ? { object: node.object.name, property: node.property.name } : null;
|
|
12511
12813
|
var isSamePlainMember = (node, access) => {
|
|
12512
12814
|
const candidate2 = plainMemberAccess(node);
|
|
12513
12815
|
return candidate2 !== null && candidate2.object === access.object && candidate2.property === access.property;
|
|
@@ -12515,19 +12817,19 @@ var isSamePlainMember = (node, access) => {
|
|
|
12515
12817
|
var nodeWithin2 = (node, container) => node.range[0] >= container.range[0] && node.range[1] <= container.range[1];
|
|
12516
12818
|
var isUseWithinValidatedBranch = (node, bindingName) => {
|
|
12517
12819
|
for (let current = node.parent; current !== void 0 && current !== null; current = current.parent) {
|
|
12518
|
-
if (current.type ===
|
|
12820
|
+
if (current.type === import_utils73.AST_NODE_TYPES.ConditionalExpression) {
|
|
12519
12821
|
const polarity = bindingValidationPolarity(current.test, bindingName);
|
|
12520
12822
|
if (polarity === "valid-when-true" && nodeWithin2(node, current.consequent) || polarity === "valid-when-false" && nodeWithin2(node, current.alternate)) {
|
|
12521
12823
|
return true;
|
|
12522
12824
|
}
|
|
12523
12825
|
}
|
|
12524
|
-
if (current.type ===
|
|
12826
|
+
if (current.type === import_utils73.AST_NODE_TYPES.IfStatement) {
|
|
12525
12827
|
const polarity = bindingValidationPolarity(current.test, bindingName);
|
|
12526
12828
|
if (polarity === "valid-when-true" && nodeWithin2(node, current.consequent) || polarity === "valid-when-false" && current.alternate !== null && nodeWithin2(node, current.alternate)) {
|
|
12527
12829
|
return true;
|
|
12528
12830
|
}
|
|
12529
12831
|
}
|
|
12530
|
-
if (current.type ===
|
|
12832
|
+
if (current.type === import_utils73.AST_NODE_TYPES.FunctionDeclaration || current.type === import_utils73.AST_NODE_TYPES.FunctionExpression || current.type === import_utils73.AST_NODE_TYPES.ArrowFunctionExpression) {
|
|
12531
12833
|
return false;
|
|
12532
12834
|
}
|
|
12533
12835
|
}
|
|
@@ -12535,32 +12837,32 @@ var isUseWithinValidatedBranch = (node, bindingName) => {
|
|
|
12535
12837
|
};
|
|
12536
12838
|
var isMemberUseWithinValidatedBranch = (node, access) => {
|
|
12537
12839
|
for (let current = node.parent; current !== void 0 && current !== null; current = current.parent) {
|
|
12538
|
-
if (current.type ===
|
|
12840
|
+
if (current.type === import_utils73.AST_NODE_TYPES.ConditionalExpression) {
|
|
12539
12841
|
const polarity = memberValidationPolarity(current.test, access);
|
|
12540
12842
|
if (polarity === "valid-when-true" && nodeWithin2(node, current.consequent) || polarity === "valid-when-false" && nodeWithin2(node, current.alternate)) {
|
|
12541
12843
|
return true;
|
|
12542
12844
|
}
|
|
12543
12845
|
}
|
|
12544
|
-
if (current.type ===
|
|
12846
|
+
if (current.type === import_utils73.AST_NODE_TYPES.IfStatement) {
|
|
12545
12847
|
const polarity = memberValidationPolarity(current.test, access);
|
|
12546
12848
|
if (polarity === "valid-when-true" && nodeWithin2(node, current.consequent) || polarity === "valid-when-false" && current.alternate !== null && nodeWithin2(node, current.alternate)) {
|
|
12547
12849
|
return true;
|
|
12548
12850
|
}
|
|
12549
12851
|
}
|
|
12550
|
-
if (current.type ===
|
|
12852
|
+
if (current.type === import_utils73.AST_NODE_TYPES.FunctionDeclaration || current.type === import_utils73.AST_NODE_TYPES.FunctionExpression || current.type === import_utils73.AST_NODE_TYPES.ArrowFunctionExpression) {
|
|
12551
12853
|
return false;
|
|
12552
12854
|
}
|
|
12553
12855
|
}
|
|
12554
12856
|
return false;
|
|
12555
12857
|
};
|
|
12556
12858
|
var memberValidationPolarity = (test, access) => {
|
|
12557
|
-
if (test.type ===
|
|
12859
|
+
if (test.type === import_utils73.AST_NODE_TYPES.UnaryExpression && test.operator === "!") {
|
|
12558
12860
|
const inner = memberValidationPolarity(test.argument, access);
|
|
12559
12861
|
return inner === "valid-when-true" ? "valid-when-false" : inner === "valid-when-false" ? "valid-when-true" : null;
|
|
12560
12862
|
}
|
|
12561
|
-
if (test.type ===
|
|
12562
|
-
const isMatchingTypeof = (node) => node.type ===
|
|
12563
|
-
const isPrimitiveType = (node) => node.type ===
|
|
12863
|
+
if (test.type === import_utils73.AST_NODE_TYPES.BinaryExpression) {
|
|
12864
|
+
const isMatchingTypeof = (node) => node.type === import_utils73.AST_NODE_TYPES.UnaryExpression && node.operator === "typeof" && isSamePlainMember(node.argument, access);
|
|
12865
|
+
const isPrimitiveType = (node) => node.type === import_utils73.AST_NODE_TYPES.Literal && typeof node.value === "string" && PRIMITIVE_TYPEOF_RESULTS.has(node.value);
|
|
12564
12866
|
if (!(isMatchingTypeof(test.left) && isPrimitiveType(test.right) || isMatchingTypeof(test.right) && isPrimitiveType(test.left))) {
|
|
12565
12867
|
return null;
|
|
12566
12868
|
}
|
|
@@ -12569,15 +12871,15 @@ var memberValidationPolarity = (test, access) => {
|
|
|
12569
12871
|
}
|
|
12570
12872
|
return test.operator === "!==" || test.operator === "!=" ? "valid-when-false" : null;
|
|
12571
12873
|
}
|
|
12572
|
-
return test.type ===
|
|
12874
|
+
return test.type === import_utils73.AST_NODE_TYPES.CallExpression && test.arguments.length === 1 && test.arguments[0] !== void 0 && test.arguments[0].type !== import_utils73.AST_NODE_TYPES.SpreadElement && isSamePlainMember(test.arguments[0], access) && test.callee.type === import_utils73.AST_NODE_TYPES.MemberExpression && !test.callee.computed && test.callee.object.type === import_utils73.AST_NODE_TYPES.Identifier && test.callee.object.name === "Array" && test.callee.property.type === import_utils73.AST_NODE_TYPES.Identifier && test.callee.property.name === "isArray" ? "valid-when-true" : null;
|
|
12573
12875
|
};
|
|
12574
12876
|
var isFullyValidatedExtractedBinding = (member, source, context) => {
|
|
12575
12877
|
const isValidationReference = (identifier) => {
|
|
12576
12878
|
for (let current = identifier.parent; current !== void 0 && current !== null; current = current.parent) {
|
|
12577
|
-
if ((current.type ===
|
|
12879
|
+
if ((current.type === import_utils73.AST_NODE_TYPES.BinaryExpression || current.type === import_utils73.AST_NODE_TYPES.CallExpression || current.type === import_utils73.AST_NODE_TYPES.UnaryExpression) && bindingValidationPolarity(current, identifier.name) !== null) {
|
|
12578
12880
|
return true;
|
|
12579
12881
|
}
|
|
12580
|
-
if (current.type !==
|
|
12882
|
+
if (current.type !== import_utils73.AST_NODE_TYPES.UnaryExpression && current.type !== import_utils73.AST_NODE_TYPES.MemberExpression && current.type !== import_utils73.AST_NODE_TYPES.CallExpression) {
|
|
12581
12883
|
return false;
|
|
12582
12884
|
}
|
|
12583
12885
|
}
|
|
@@ -12585,7 +12887,7 @@ var isFullyValidatedExtractedBinding = (member, source, context) => {
|
|
|
12585
12887
|
};
|
|
12586
12888
|
const isGuardedUse = (identifier) => {
|
|
12587
12889
|
for (let current = identifier.parent; current !== void 0 && current !== null; current = current.parent) {
|
|
12588
|
-
if (current.type ===
|
|
12890
|
+
if (current.type === import_utils73.AST_NODE_TYPES.ConditionalExpression) {
|
|
12589
12891
|
const polarity = bindingValidationPolarity(current.test, identifier.name);
|
|
12590
12892
|
if (polarity === "valid-when-true" && nodeWithin2(identifier, current.consequent)) {
|
|
12591
12893
|
return true;
|
|
@@ -12594,7 +12896,7 @@ var isFullyValidatedExtractedBinding = (member, source, context) => {
|
|
|
12594
12896
|
return true;
|
|
12595
12897
|
}
|
|
12596
12898
|
}
|
|
12597
|
-
if (current.type ===
|
|
12899
|
+
if (current.type === import_utils73.AST_NODE_TYPES.IfStatement) {
|
|
12598
12900
|
const polarity = bindingValidationPolarity(current.test, identifier.name);
|
|
12599
12901
|
if (polarity === "valid-when-true" && nodeWithin2(identifier, current.consequent)) {
|
|
12600
12902
|
return true;
|
|
@@ -12603,14 +12905,14 @@ var isFullyValidatedExtractedBinding = (member, source, context) => {
|
|
|
12603
12905
|
return true;
|
|
12604
12906
|
}
|
|
12605
12907
|
}
|
|
12606
|
-
if (current.type ===
|
|
12908
|
+
if (current.type === import_utils73.AST_NODE_TYPES.FunctionDeclaration || current.type === import_utils73.AST_NODE_TYPES.FunctionExpression || current.type === import_utils73.AST_NODE_TYPES.ArrowFunctionExpression) {
|
|
12607
12909
|
return false;
|
|
12608
12910
|
}
|
|
12609
12911
|
}
|
|
12610
12912
|
return false;
|
|
12611
12913
|
};
|
|
12612
12914
|
const declarator = member.parent;
|
|
12613
|
-
if (declarator.type !==
|
|
12915
|
+
if (declarator.type !== import_utils73.AST_NODE_TYPES.VariableDeclarator || declarator.init !== member || declarator.id.type !== import_utils73.AST_NODE_TYPES.Identifier || declarator.parent.type !== import_utils73.AST_NODE_TYPES.VariableDeclaration || declarator.parent.kind !== "const") {
|
|
12614
12916
|
return false;
|
|
12615
12917
|
}
|
|
12616
12918
|
const extracted = context.sourceCode.getDeclaredVariables(declarator)[0];
|
|
@@ -12618,7 +12920,7 @@ var isFullyValidatedExtractedBinding = (member, source, context) => {
|
|
|
12618
12920
|
let hasValueUse = false;
|
|
12619
12921
|
for (const reference of extracted.references) {
|
|
12620
12922
|
const identifier = reference.identifier;
|
|
12621
|
-
if (identifier.type !==
|
|
12923
|
+
if (identifier.type !== import_utils73.AST_NODE_TYPES.Identifier) return false;
|
|
12622
12924
|
if (nodeWithin2(identifier, declarator)) continue;
|
|
12623
12925
|
if (isValidationReference(identifier)) continue;
|
|
12624
12926
|
hasValueUse = true;
|
|
@@ -12631,17 +12933,17 @@ var isGuardTestPosition = (node) => {
|
|
|
12631
12933
|
let parent = current.parent;
|
|
12632
12934
|
while (parent !== void 0 && parent !== null) {
|
|
12633
12935
|
switch (parent.type) {
|
|
12634
|
-
case
|
|
12635
|
-
case
|
|
12636
|
-
case
|
|
12936
|
+
case import_utils73.AST_NODE_TYPES.UnaryExpression:
|
|
12937
|
+
case import_utils73.AST_NODE_TYPES.LogicalExpression:
|
|
12938
|
+
case import_utils73.AST_NODE_TYPES.ChainExpression:
|
|
12637
12939
|
current = parent;
|
|
12638
12940
|
parent = parent.parent;
|
|
12639
12941
|
continue;
|
|
12640
|
-
case
|
|
12641
|
-
case
|
|
12642
|
-
case
|
|
12643
|
-
case
|
|
12644
|
-
case
|
|
12942
|
+
case import_utils73.AST_NODE_TYPES.IfStatement:
|
|
12943
|
+
case import_utils73.AST_NODE_TYPES.ConditionalExpression:
|
|
12944
|
+
case import_utils73.AST_NODE_TYPES.WhileStatement:
|
|
12945
|
+
case import_utils73.AST_NODE_TYPES.DoWhileStatement:
|
|
12946
|
+
case import_utils73.AST_NODE_TYPES.ForStatement:
|
|
12645
12947
|
return parent.test === current;
|
|
12646
12948
|
default:
|
|
12647
12949
|
return false;
|
|
@@ -12650,8 +12952,8 @@ var isGuardTestPosition = (node) => {
|
|
|
12650
12952
|
return false;
|
|
12651
12953
|
};
|
|
12652
12954
|
var unvalidatedVariableRef = (node, scope, tracked) => {
|
|
12653
|
-
const unwrapped =
|
|
12654
|
-
if (unwrapped === null || unwrapped.type !==
|
|
12955
|
+
const unwrapped = unwrap5(node);
|
|
12956
|
+
if (unwrapped === null || unwrapped.type !== import_utils73.AST_NODE_TYPES.Identifier) {
|
|
12655
12957
|
return null;
|
|
12656
12958
|
}
|
|
12657
12959
|
const variable = findVariable2(scope, unwrapped.name);
|
|
@@ -12679,8 +12981,8 @@ var prefer_schema_for_api_payload_default = createRule({
|
|
|
12679
12981
|
const aliasGroups = /* @__PURE__ */ new Map();
|
|
12680
12982
|
const localFileTextVariables = /* @__PURE__ */ new Set();
|
|
12681
12983
|
const localFileTextRef = (node, scope) => {
|
|
12682
|
-
const unwrapped =
|
|
12683
|
-
if (unwrapped?.type !==
|
|
12984
|
+
const unwrapped = unwrap5(node);
|
|
12985
|
+
if (unwrapped?.type !== import_utils73.AST_NODE_TYPES.Identifier) return null;
|
|
12684
12986
|
const variable = findVariable2(scope, unwrapped.name);
|
|
12685
12987
|
return variable !== null && localFileTextVariables.has(variable) ? variable : null;
|
|
12686
12988
|
};
|
|
@@ -12749,7 +13051,7 @@ var prefer_schema_for_api_payload_default = createRule({
|
|
|
12749
13051
|
return {
|
|
12750
13052
|
VariableDeclarator(node) {
|
|
12751
13053
|
const scope = context.sourceCode.getScope(node);
|
|
12752
|
-
if (node.id.type ===
|
|
13054
|
+
if (node.id.type === import_utils73.AST_NODE_TYPES.Identifier) {
|
|
12753
13055
|
const variable = context.sourceCode.getDeclaredVariables(node)[0];
|
|
12754
13056
|
if (variable !== void 0) {
|
|
12755
13057
|
updateLocalFileText(variable, node.init, scope);
|
|
@@ -12757,7 +13059,7 @@ var prefer_schema_for_api_payload_default = createRule({
|
|
|
12757
13059
|
trackInitializer(node, scope);
|
|
12758
13060
|
return;
|
|
12759
13061
|
}
|
|
12760
|
-
if (node.id.type ===
|
|
13062
|
+
if (node.id.type === import_utils73.AST_NODE_TYPES.ObjectPattern || node.id.type === import_utils73.AST_NODE_TYPES.ArrayPattern) {
|
|
12761
13063
|
if (isRawPayloadSource(
|
|
12762
13064
|
node.init,
|
|
12763
13065
|
(candidate2) => localFileTextRef(candidate2, scope) !== null
|
|
@@ -12774,7 +13076,7 @@ var prefer_schema_for_api_payload_default = createRule({
|
|
|
12774
13076
|
},
|
|
12775
13077
|
AssignmentExpression(node) {
|
|
12776
13078
|
const scope = context.sourceCode.getScope(node);
|
|
12777
|
-
if (node.left.type ===
|
|
13079
|
+
if (node.left.type === import_utils73.AST_NODE_TYPES.Identifier) {
|
|
12778
13080
|
const variable = findVariable2(scope, node.left.name);
|
|
12779
13081
|
if (variable === null) return;
|
|
12780
13082
|
const isLocalText = (candidate2) => localFileTextRef(candidate2, scope) !== null;
|
|
@@ -12788,7 +13090,7 @@ var prefer_schema_for_api_payload_default = createRule({
|
|
|
12788
13090
|
}
|
|
12789
13091
|
return;
|
|
12790
13092
|
}
|
|
12791
|
-
if (node.left.type ===
|
|
13093
|
+
if (node.left.type === import_utils73.AST_NODE_TYPES.ObjectPattern || node.left.type === import_utils73.AST_NODE_TYPES.ArrayPattern) {
|
|
12792
13094
|
if (isRawPayloadSource(
|
|
12793
13095
|
node.right,
|
|
12794
13096
|
(candidate2) => localFileTextRef(candidate2, scope) !== null
|
|
@@ -12808,15 +13110,15 @@ var prefer_schema_for_api_payload_default = createRule({
|
|
|
12808
13110
|
}
|
|
12809
13111
|
},
|
|
12810
13112
|
CallExpression(node) {
|
|
12811
|
-
if (node.callee.type !==
|
|
13113
|
+
if (node.callee.type !== import_utils73.AST_NODE_TYPES.Identifier) return;
|
|
12812
13114
|
if (!GUARD_NAME_RE.test(node.callee.name) && !isGuardTestPosition(node)) {
|
|
12813
13115
|
return;
|
|
12814
13116
|
}
|
|
12815
13117
|
const scope = context.sourceCode.getScope(node);
|
|
12816
13118
|
for (const arg of node.arguments) {
|
|
12817
|
-
if (arg.type ===
|
|
12818
|
-
const unwrapped =
|
|
12819
|
-
if (unwrapped === null || unwrapped.type !==
|
|
13119
|
+
if (arg.type === import_utils73.AST_NODE_TYPES.SpreadElement) continue;
|
|
13120
|
+
const unwrapped = unwrap5(arg);
|
|
13121
|
+
if (unwrapped === null || unwrapped.type !== import_utils73.AST_NODE_TYPES.Identifier) {
|
|
12820
13122
|
continue;
|
|
12821
13123
|
}
|
|
12822
13124
|
const variable = findVariable2(scope, unwrapped.name);
|
|
@@ -12827,20 +13129,20 @@ var prefer_schema_for_api_payload_default = createRule({
|
|
|
12827
13129
|
if (isInsideAssertion(node)) return;
|
|
12828
13130
|
if (isValidationRead(node)) return;
|
|
12829
13131
|
const scope = context.sourceCode.getScope(node);
|
|
12830
|
-
const obj =
|
|
13132
|
+
const obj = unwrap5(node.object);
|
|
12831
13133
|
if (isRawPayloadSource(
|
|
12832
13134
|
obj,
|
|
12833
13135
|
(candidate2) => localFileTextRef(candidate2, scope) !== null
|
|
12834
13136
|
)) {
|
|
12835
13137
|
const parent = node.parent;
|
|
12836
|
-
if (parent.type ===
|
|
13138
|
+
if (parent.type === import_utils73.AST_NODE_TYPES.CallExpression && parent.callee === node && node.property.type === import_utils73.AST_NODE_TYPES.Identifier && (node.property.name === "parse" || node.property.name === "safeParse" || PROMISE_CHAIN_METHODS.has(node.property.name))) {
|
|
12837
13139
|
return;
|
|
12838
13140
|
}
|
|
12839
13141
|
context.report({ node, messageId: "unparsedJsonAccess" });
|
|
12840
13142
|
return;
|
|
12841
13143
|
}
|
|
12842
|
-
const variable = obj?.type ===
|
|
12843
|
-
if (variable !== null && obj?.type ===
|
|
13144
|
+
const variable = obj?.type === import_utils73.AST_NODE_TYPES.Identifier ? unvalidatedVariableRef(obj, scope, unvalidatedVariables) : null;
|
|
13145
|
+
if (variable !== null && obj?.type === import_utils73.AST_NODE_TYPES.Identifier) {
|
|
12844
13146
|
if (isUseWithinValidatedBranch(node, obj.name)) {
|
|
12845
13147
|
return;
|
|
12846
13148
|
}
|
|
@@ -12859,8 +13161,142 @@ var prefer_schema_for_api_payload_default = createRule({
|
|
|
12859
13161
|
}
|
|
12860
13162
|
});
|
|
12861
13163
|
|
|
13164
|
+
// src/rules/prefer-shared-zod-enum.ts
|
|
13165
|
+
var import_utils74 = require("@typescript-eslint/utils");
|
|
13166
|
+
var PREFER_SHARED_ZOD_ENUM_DOCUMENTATION = {
|
|
13167
|
+
summary: "Give literal Zod enum domains one reusable module-level schema.",
|
|
13168
|
+
rationale: "Inline or repeated literal domains hide a reusable contract and allow equivalent fields to drift independently.",
|
|
13169
|
+
remediation: "Declare a module-level named Zod enum schema and reuse it at each field or contract site.",
|
|
13170
|
+
category: "maintainability",
|
|
13171
|
+
limitations: ["Only direct z.enum calls with string-literal arrays are inspected; computed domains require review."],
|
|
13172
|
+
examples: [
|
|
13173
|
+
{ 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 },
|
|
13174
|
+
{ id: "inline-provider", title: "Do not inline enum domains in object fields", outcome: "match", files: [{ path: "src/provider.ts", source: "import { z } from 'zod'; const JobSchema = z.object({ provider: z.enum(['agy', 'claude', 'sol']) });" }], focusPath: "src/provider.ts", expectedCount: 1, public: true }
|
|
13175
|
+
]
|
|
13176
|
+
};
|
|
13177
|
+
function literalDomain(node) {
|
|
13178
|
+
const [argument] = node.arguments;
|
|
13179
|
+
if (argument?.type !== import_utils74.AST_NODE_TYPES.ArrayExpression || argument.elements.length < 2) return null;
|
|
13180
|
+
const values = [];
|
|
13181
|
+
for (const element of argument.elements) {
|
|
13182
|
+
if (element?.type !== import_utils74.AST_NODE_TYPES.Literal || typeof element.value !== "string") return null;
|
|
13183
|
+
values.push(element.value);
|
|
13184
|
+
}
|
|
13185
|
+
return values;
|
|
13186
|
+
}
|
|
13187
|
+
function isModuleLevelNamedSchema(node) {
|
|
13188
|
+
let current = node;
|
|
13189
|
+
while (current.parent?.type === import_utils74.AST_NODE_TYPES.MemberExpression && current.parent.object === current) {
|
|
13190
|
+
current = current.parent;
|
|
13191
|
+
if (current.parent?.type === import_utils74.AST_NODE_TYPES.CallExpression && current.parent.callee === current) current = current.parent;
|
|
13192
|
+
}
|
|
13193
|
+
const declarator = current.parent;
|
|
13194
|
+
if (declarator?.type !== import_utils74.AST_NODE_TYPES.VariableDeclarator || declarator.init !== current || declarator.id.type !== import_utils74.AST_NODE_TYPES.Identifier || declarator.parent.type !== import_utils74.AST_NODE_TYPES.VariableDeclaration) return false;
|
|
13195
|
+
const declarationParent = declarator.parent.parent;
|
|
13196
|
+
return declarationParent.type === import_utils74.AST_NODE_TYPES.Program || declarationParent.type === import_utils74.AST_NODE_TYPES.ExportNamedDeclaration && declarationParent.parent.type === import_utils74.AST_NODE_TYPES.Program;
|
|
13197
|
+
}
|
|
13198
|
+
var prefer_shared_zod_enum_default = createRule({
|
|
13199
|
+
name: "prefer-shared-zod-enum",
|
|
13200
|
+
documentation: PREFER_SHARED_ZOD_ENUM_DOCUMENTATION,
|
|
13201
|
+
meta: {
|
|
13202
|
+
type: "suggestion",
|
|
13203
|
+
docs: { description: "Give literal Zod enum domains one reusable module-level schema." },
|
|
13204
|
+
schema: [],
|
|
13205
|
+
messages: {
|
|
13206
|
+
shareEnumDomain: "Extract this literal Zod enum to one module-level named schema and reuse it."
|
|
13207
|
+
}
|
|
13208
|
+
},
|
|
13209
|
+
defaultOptions: [],
|
|
13210
|
+
create(context) {
|
|
13211
|
+
if (isTestFile(context.filename) || isGeneratedFile(context.filename, context.sourceCode.text)) return {};
|
|
13212
|
+
const zodBindings = /* @__PURE__ */ new Set();
|
|
13213
|
+
const seen = /* @__PURE__ */ new Set();
|
|
13214
|
+
return {
|
|
13215
|
+
ImportDeclaration(node) {
|
|
13216
|
+
if (!isZodModule(node.source.value)) return;
|
|
13217
|
+
for (const specifier of node.specifiers) {
|
|
13218
|
+
if (specifier.type === import_utils74.AST_NODE_TYPES.ImportNamespaceSpecifier || specifier.type === import_utils74.AST_NODE_TYPES.ImportDefaultSpecifier || specifier.type === import_utils74.AST_NODE_TYPES.ImportSpecifier && specifier.imported.type === import_utils74.AST_NODE_TYPES.Identifier && specifier.imported.name === "z") zodBindings.add(specifier.local.name);
|
|
13219
|
+
}
|
|
13220
|
+
},
|
|
13221
|
+
CallExpression(node) {
|
|
13222
|
+
if (node.callee.type !== import_utils74.AST_NODE_TYPES.MemberExpression || node.callee.computed || node.callee.object.type !== import_utils74.AST_NODE_TYPES.Identifier || !zodBindings.has(node.callee.object.name) || node.callee.property.type !== import_utils74.AST_NODE_TYPES.Identifier || node.callee.property.name !== "enum") return;
|
|
13223
|
+
const domain = literalDomain(node);
|
|
13224
|
+
if (domain === null) return;
|
|
13225
|
+
const key = JSON.stringify(domain);
|
|
13226
|
+
const inline = !isModuleLevelNamedSchema(node);
|
|
13227
|
+
if (inline || seen.has(key))
|
|
13228
|
+
context.report({ node, messageId: "shareEnumDomain" });
|
|
13229
|
+
else seen.add(key);
|
|
13230
|
+
}
|
|
13231
|
+
};
|
|
13232
|
+
}
|
|
13233
|
+
});
|
|
13234
|
+
|
|
13235
|
+
// src/rules/prefer-switch-for-repeated-equality.ts
|
|
13236
|
+
var import_utils75 = require("@typescript-eslint/utils");
|
|
13237
|
+
var PREFER_SWITCH_FOR_REPEATED_EQUALITY_DOCUMENTATION = {
|
|
13238
|
+
summary: "Prefer switch over long if/else-if chains that compare one value for strict equality.",
|
|
13239
|
+
rationale: "A switch makes finite dispatch cases visually uniform and easier to extend without duplicating the discriminant.",
|
|
13240
|
+
remediation: "Replace three or more strict-equality branches over the same discriminant with a switch; keep if statements for ranges, guards, and heterogeneous predicates.",
|
|
13241
|
+
category: "maintainability",
|
|
13242
|
+
limitations: [
|
|
13243
|
+
"Only direct if/else-if chains with at least three strict-equality tests are reported.",
|
|
13244
|
+
"Case values may be literals, enum-like member references, or upper-case named constants; dynamic expressions are excluded.",
|
|
13245
|
+
"The rule deliberately ignores compound predicates, loose equality, ranges, and chains that compare different discriminants."
|
|
13246
|
+
],
|
|
13247
|
+
examples: [
|
|
13248
|
+
{ 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 },
|
|
13249
|
+
{ 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 }
|
|
13250
|
+
]
|
|
13251
|
+
};
|
|
13252
|
+
function discriminantText(sourceCode, test) {
|
|
13253
|
+
if (test.type !== import_utils75.AST_NODE_TYPES.BinaryExpression || test.operator !== "===") return null;
|
|
13254
|
+
const leftIsCase = isCaseValue(test.left);
|
|
13255
|
+
const rightIsCase = isCaseValue(test.right);
|
|
13256
|
+
if (leftIsCase === rightIsCase) return null;
|
|
13257
|
+
return sourceCode.getText(leftIsCase ? test.right : test.left);
|
|
13258
|
+
}
|
|
13259
|
+
function isCaseValue(node) {
|
|
13260
|
+
if (node.type === import_utils75.AST_NODE_TYPES.Literal) return true;
|
|
13261
|
+
if (node.type === import_utils75.AST_NODE_TYPES.Identifier) return /^[A-Z][A-Z0-9_]*$/u.test(node.name);
|
|
13262
|
+
if (node.type !== import_utils75.AST_NODE_TYPES.MemberExpression || node.computed) return false;
|
|
13263
|
+
return node.property.type === import_utils75.AST_NODE_TYPES.Identifier && (node.object.type === import_utils75.AST_NODE_TYPES.Identifier || isCaseValue(node.object));
|
|
13264
|
+
}
|
|
13265
|
+
var prefer_switch_for_repeated_equality_default = createRule({
|
|
13266
|
+
name: "prefer-switch-for-repeated-equality",
|
|
13267
|
+
documentation: PREFER_SWITCH_FOR_REPEATED_EQUALITY_DOCUMENTATION,
|
|
13268
|
+
meta: {
|
|
13269
|
+
type: "suggestion",
|
|
13270
|
+
docs: { description: "Prefer switch over long if/else-if chains that compare one value for strict equality." },
|
|
13271
|
+
schema: [],
|
|
13272
|
+
messages: {
|
|
13273
|
+
preferSwitch: "This if/else-if chain repeatedly compares `{{discriminant}}`; use a switch for the finite cases."
|
|
13274
|
+
}
|
|
13275
|
+
},
|
|
13276
|
+
defaultOptions: [],
|
|
13277
|
+
create(context) {
|
|
13278
|
+
return {
|
|
13279
|
+
IfStatement(node) {
|
|
13280
|
+
if (node.parent.type === import_utils75.AST_NODE_TYPES.IfStatement && node.parent.alternate === node) return;
|
|
13281
|
+
const first = discriminantText(context.sourceCode, node.test);
|
|
13282
|
+
if (first === null) return;
|
|
13283
|
+
let count = 1;
|
|
13284
|
+
let current = node.alternate;
|
|
13285
|
+
while (current?.type === import_utils75.AST_NODE_TYPES.IfStatement) {
|
|
13286
|
+
if (discriminantText(context.sourceCode, current.test) !== first) return;
|
|
13287
|
+
count += 1;
|
|
13288
|
+
current = current.alternate;
|
|
13289
|
+
}
|
|
13290
|
+
if (count >= 3) {
|
|
13291
|
+
context.report({ node, messageId: "preferSwitch", data: { discriminant: first } });
|
|
13292
|
+
}
|
|
13293
|
+
}
|
|
13294
|
+
};
|
|
13295
|
+
}
|
|
13296
|
+
});
|
|
13297
|
+
|
|
12862
13298
|
// src/rules/prefer-semantic-colors.ts
|
|
12863
|
-
var
|
|
13299
|
+
var import_utils76 = require("@typescript-eslint/utils");
|
|
12864
13300
|
var import_fs = require("fs");
|
|
12865
13301
|
var import_path = require("path");
|
|
12866
13302
|
|
|
@@ -12972,7 +13408,7 @@ var SVG_EXEMPT_COLOR_VALUES = /* @__PURE__ */ new Set([
|
|
|
12972
13408
|
var isInsideSvg = (node) => {
|
|
12973
13409
|
let current = node.parent;
|
|
12974
13410
|
while (current !== void 0 && current !== null) {
|
|
12975
|
-
if (current.type ===
|
|
13411
|
+
if (current.type === import_utils76.AST_NODE_TYPES.JSXElement) {
|
|
12976
13412
|
const name = jsxElementName(current);
|
|
12977
13413
|
if (name !== null && isSvgLikeElementName(name)) return true;
|
|
12978
13414
|
}
|
|
@@ -12982,8 +13418,8 @@ var isInsideSvg = (node) => {
|
|
|
12982
13418
|
};
|
|
12983
13419
|
function jsxElementName(node) {
|
|
12984
13420
|
const name = node.openingElement.name;
|
|
12985
|
-
if (name.type ===
|
|
12986
|
-
if (name.type ===
|
|
13421
|
+
if (name.type === import_utils76.AST_NODE_TYPES.JSXIdentifier) return name.name;
|
|
13422
|
+
if (name.type === import_utils76.AST_NODE_TYPES.JSXMemberExpression && name.property.type === import_utils76.AST_NODE_TYPES.JSXIdentifier) {
|
|
12987
13423
|
return name.property.name;
|
|
12988
13424
|
}
|
|
12989
13425
|
return null;
|
|
@@ -13009,7 +13445,7 @@ function isSvgLikeElementName(name) {
|
|
|
13009
13445
|
var isInsideIconFactoryPath = (node) => {
|
|
13010
13446
|
let current = node.parent;
|
|
13011
13447
|
while (current !== void 0 && current !== null) {
|
|
13012
|
-
if (current.type ===
|
|
13448
|
+
if (current.type === import_utils76.AST_NODE_TYPES.Property && propName(current.key) === "path" && current.parent.type === import_utils76.AST_NODE_TYPES.ObjectExpression && current.parent.parent.type === import_utils76.AST_NODE_TYPES.CallExpression && current.parent.parent.callee.type === import_utils76.AST_NODE_TYPES.Identifier && current.parent.parent.callee.name === "createIcon") {
|
|
13013
13449
|
return true;
|
|
13014
13450
|
}
|
|
13015
13451
|
current = current.parent;
|
|
@@ -13143,12 +13579,12 @@ var expandWorkspaceGlob = (root, glob) => {
|
|
|
13143
13579
|
return (0, import_fs.readdirSync)(parent, { withFileTypes: true }).filter((entry) => entry.isDirectory() && !entry.name.startsWith(".")).map((entry) => (0, import_path.join)(parent, entry.name));
|
|
13144
13580
|
};
|
|
13145
13581
|
var propName = (key) => {
|
|
13146
|
-
if (key.type ===
|
|
13147
|
-
if (key.type ===
|
|
13582
|
+
if (key.type === import_utils76.AST_NODE_TYPES.Identifier) return key.name;
|
|
13583
|
+
if (key.type === import_utils76.AST_NODE_TYPES.Literal && typeof key.value === "string") return key.value;
|
|
13148
13584
|
return null;
|
|
13149
13585
|
};
|
|
13150
13586
|
var staticallyImportsEmailOrPdfRenderer = (program) => program.body.some((statement) => {
|
|
13151
|
-
if (statement.type !==
|
|
13587
|
+
if (statement.type !== import_utils76.AST_NODE_TYPES.ImportDeclaration && statement.type !== import_utils76.AST_NODE_TYPES.ExportNamedDeclaration && statement.type !== import_utils76.AST_NODE_TYPES.ExportAllDeclaration) {
|
|
13152
13588
|
return false;
|
|
13153
13589
|
}
|
|
13154
13590
|
return statement.source !== null && typeof statement.source.value === "string" && EMAIL_OR_PDF_MODULE_RE.test(statement.source.value);
|
|
@@ -13185,43 +13621,43 @@ var prefer_semantic_colors_default = createRule({
|
|
|
13185
13621
|
}
|
|
13186
13622
|
let importsEmailOrPdfRenderer = false;
|
|
13187
13623
|
const pendingReports = [];
|
|
13188
|
-
const
|
|
13624
|
+
const report2 = (node, messageId, data) => {
|
|
13189
13625
|
pendingReports.push({ node, messageId, data });
|
|
13190
13626
|
};
|
|
13191
13627
|
const reportClasses = (value, node) => {
|
|
13192
13628
|
for (const token of classTokens(value)) {
|
|
13193
13629
|
const base = tailwindBase(token);
|
|
13194
13630
|
if (RAW_PALETTE_RE.test(base)) {
|
|
13195
|
-
|
|
13631
|
+
report2(node, "rawPalette", { class: token });
|
|
13196
13632
|
} else if (ARBITRARY_COLOR_RE.test(base) && !CSS_VAR_REFERENCE_RE.test(base)) {
|
|
13197
|
-
|
|
13633
|
+
report2(node, "arbitraryColor", { class: token });
|
|
13198
13634
|
}
|
|
13199
13635
|
}
|
|
13200
13636
|
};
|
|
13201
13637
|
const checkClassNode = (node) => {
|
|
13202
13638
|
if (node === null) return;
|
|
13203
13639
|
switch (node.type) {
|
|
13204
|
-
case
|
|
13640
|
+
case import_utils76.AST_NODE_TYPES.Literal:
|
|
13205
13641
|
if (typeof node.value === "string") reportClasses(node.value, node);
|
|
13206
13642
|
break;
|
|
13207
|
-
case
|
|
13643
|
+
case import_utils76.AST_NODE_TYPES.TemplateLiteral:
|
|
13208
13644
|
for (const quasi of node.quasis) reportClasses(quasi.value.cooked ?? "", quasi);
|
|
13209
13645
|
break;
|
|
13210
|
-
case
|
|
13646
|
+
case import_utils76.AST_NODE_TYPES.ArrayExpression:
|
|
13211
13647
|
for (const element of node.elements) {
|
|
13212
|
-
if (element !== null && element.type !==
|
|
13648
|
+
if (element !== null && element.type !== import_utils76.AST_NODE_TYPES.SpreadElement) checkClassNode(element);
|
|
13213
13649
|
}
|
|
13214
13650
|
break;
|
|
13215
|
-
case
|
|
13651
|
+
case import_utils76.AST_NODE_TYPES.ObjectExpression:
|
|
13216
13652
|
for (const property of node.properties) {
|
|
13217
|
-
if (property.type ===
|
|
13653
|
+
if (property.type === import_utils76.AST_NODE_TYPES.Property) checkClassNode(property.value);
|
|
13218
13654
|
}
|
|
13219
13655
|
break;
|
|
13220
|
-
case
|
|
13656
|
+
case import_utils76.AST_NODE_TYPES.ConditionalExpression:
|
|
13221
13657
|
checkClassNode(node.consequent);
|
|
13222
13658
|
checkClassNode(node.alternate);
|
|
13223
13659
|
break;
|
|
13224
|
-
case
|
|
13660
|
+
case import_utils76.AST_NODE_TYPES.LogicalExpression:
|
|
13225
13661
|
checkClassNode(node.right);
|
|
13226
13662
|
break;
|
|
13227
13663
|
default:
|
|
@@ -13229,32 +13665,32 @@ var prefer_semantic_colors_default = createRule({
|
|
|
13229
13665
|
}
|
|
13230
13666
|
};
|
|
13231
13667
|
const checkColorValueNode = (node) => {
|
|
13232
|
-
if (node.type ===
|
|
13233
|
-
|
|
13668
|
+
if (node.type === import_utils76.AST_NODE_TYPES.Literal && typeof node.value === "string" && RAW_COLOR_VALUE_RE.test(node.value) && !CSS_VAR_REFERENCE_RE.test(node.value)) {
|
|
13669
|
+
report2(node, "inlineColor", { value: node.value });
|
|
13234
13670
|
}
|
|
13235
13671
|
};
|
|
13236
13672
|
return {
|
|
13237
13673
|
"JSXAttribute[name.name='className']"(node) {
|
|
13238
13674
|
if (node.value === null) return;
|
|
13239
|
-
if (node.value.type ===
|
|
13240
|
-
else if (node.value.type ===
|
|
13241
|
-
if (node.value.expression.type !==
|
|
13675
|
+
if (node.value.type === import_utils76.AST_NODE_TYPES.Literal) checkClassNode(node.value);
|
|
13676
|
+
else if (node.value.type === import_utils76.AST_NODE_TYPES.JSXExpressionContainer) {
|
|
13677
|
+
if (node.value.expression.type !== import_utils76.AST_NODE_TYPES.JSXEmptyExpression) {
|
|
13242
13678
|
checkClassNode(node.value.expression);
|
|
13243
13679
|
}
|
|
13244
13680
|
}
|
|
13245
13681
|
},
|
|
13246
13682
|
CallExpression(node) {
|
|
13247
|
-
if (node.callee.type ===
|
|
13683
|
+
if (node.callee.type === import_utils76.AST_NODE_TYPES.Identifier && node.callee.name === "require" && node.arguments[0]?.type === import_utils76.AST_NODE_TYPES.Literal && typeof node.arguments[0].value === "string" && EMAIL_OR_PDF_MODULE_RE.test(node.arguments[0].value)) {
|
|
13248
13684
|
importsEmailOrPdfRenderer = true;
|
|
13249
13685
|
}
|
|
13250
|
-
if (node.callee.type ===
|
|
13686
|
+
if (node.callee.type === import_utils76.AST_NODE_TYPES.Identifier && CLASS_FNS.has(node.callee.name)) {
|
|
13251
13687
|
for (const arg of node.arguments) {
|
|
13252
|
-
if (arg.type !==
|
|
13688
|
+
if (arg.type !== import_utils76.AST_NODE_TYPES.SpreadElement) checkClassNode(arg);
|
|
13253
13689
|
}
|
|
13254
13690
|
}
|
|
13255
13691
|
},
|
|
13256
13692
|
VariableDeclarator(node) {
|
|
13257
|
-
if (node.id.type ===
|
|
13693
|
+
if (node.id.type === import_utils76.AST_NODE_TYPES.Identifier && CLASS_NAME_RE.test(node.id.name)) {
|
|
13258
13694
|
checkClassNode(node.init);
|
|
13259
13695
|
}
|
|
13260
13696
|
},
|
|
@@ -13264,9 +13700,9 @@ var prefer_semantic_colors_default = createRule({
|
|
|
13264
13700
|
},
|
|
13265
13701
|
// SVG artwork colors are exempt; component presentation colors still report.
|
|
13266
13702
|
"JSXAttribute[name.name=/^(fill|stroke|color)$/]"(node) {
|
|
13267
|
-
if (node.value?.type !==
|
|
13703
|
+
if (node.value?.type !== import_utils76.AST_NODE_TYPES.Literal) return;
|
|
13268
13704
|
const owner = node.parent.name;
|
|
13269
|
-
if (owner.type ===
|
|
13705
|
+
if (owner.type === import_utils76.AST_NODE_TYPES.JSXIdentifier && SVG_SHAPE_PRIMITIVES.has(owner.name)) {
|
|
13270
13706
|
return;
|
|
13271
13707
|
}
|
|
13272
13708
|
if (typeof node.value.value === "string" && SVG_EXEMPT_COLOR_VALUES.has(node.value.value.toLowerCase())) {
|
|
@@ -13280,7 +13716,7 @@ var prefer_semantic_colors_default = createRule({
|
|
|
13280
13716
|
if (name !== null && STYLE_COLOR_PROPS.has(name)) checkColorValueNode(node.value);
|
|
13281
13717
|
},
|
|
13282
13718
|
ImportExpression(node) {
|
|
13283
|
-
if (node.source.type ===
|
|
13719
|
+
if (node.source.type === import_utils76.AST_NODE_TYPES.Literal && typeof node.source.value === "string" && EMAIL_OR_PDF_MODULE_RE.test(node.source.value)) {
|
|
13284
13720
|
importsEmailOrPdfRenderer = true;
|
|
13285
13721
|
}
|
|
13286
13722
|
},
|
|
@@ -13293,7 +13729,7 @@ var prefer_semantic_colors_default = createRule({
|
|
|
13293
13729
|
});
|
|
13294
13730
|
|
|
13295
13731
|
// src/rules/prefer-server-actions.ts
|
|
13296
|
-
var
|
|
13732
|
+
var import_utils77 = require("@typescript-eslint/utils");
|
|
13297
13733
|
var PREFER_SERVER_ACTIONS_DOCUMENTATION = {
|
|
13298
13734
|
summary: "Prefer Next.js Server Actions over /api/* mutations.",
|
|
13299
13735
|
rationale: "Server Actions preserve typed application calls and avoid an internal JSON request-response boundary.",
|
|
@@ -13482,7 +13918,7 @@ var prefer_server_actions_default = createRule({
|
|
|
13482
13918
|
});
|
|
13483
13919
|
|
|
13484
13920
|
// src/rules/prefer-whole-object-assertion.ts
|
|
13485
|
-
var
|
|
13921
|
+
var import_utils78 = require("@typescript-eslint/utils");
|
|
13486
13922
|
var MERGEABLE_MATCHERS = /* @__PURE__ */ new Set(["toBe", "toEqual", "toStrictEqual"]);
|
|
13487
13923
|
var SYNTHETIC_LITERAL_MATCHERS = /* @__PURE__ */ new Map([
|
|
13488
13924
|
["toBeNull", "null"],
|
|
@@ -13507,11 +13943,11 @@ var PREFER_WHOLE_OBJECT_ASSERTION_DOCUMENTATION = {
|
|
|
13507
13943
|
};
|
|
13508
13944
|
function literalText(node, getText) {
|
|
13509
13945
|
switch (node.type) {
|
|
13510
|
-
case
|
|
13946
|
+
case import_utils78.AST_NODE_TYPES.Literal:
|
|
13511
13947
|
return "regex" in node ? null : getText(node);
|
|
13512
|
-
case
|
|
13948
|
+
case import_utils78.AST_NODE_TYPES.TemplateLiteral:
|
|
13513
13949
|
return node.expressions.length === 0 ? getText(node) : null;
|
|
13514
|
-
case
|
|
13950
|
+
case import_utils78.AST_NODE_TYPES.UnaryExpression:
|
|
13515
13951
|
return NUMERIC_SIGNS2.has(node.operator) && literalText(node.argument, getText) !== null ? getText(node) : null;
|
|
13516
13952
|
default:
|
|
13517
13953
|
return null;
|
|
@@ -13519,15 +13955,15 @@ function literalText(node, getText) {
|
|
|
13519
13955
|
}
|
|
13520
13956
|
function isPureReceiver(node) {
|
|
13521
13957
|
switch (node.type) {
|
|
13522
|
-
case
|
|
13523
|
-
case
|
|
13958
|
+
case import_utils78.AST_NODE_TYPES.Identifier:
|
|
13959
|
+
case import_utils78.AST_NODE_TYPES.ThisExpression:
|
|
13524
13960
|
return true;
|
|
13525
|
-
case
|
|
13961
|
+
case import_utils78.AST_NODE_TYPES.MemberExpression:
|
|
13526
13962
|
if (node.optional) {
|
|
13527
13963
|
return false;
|
|
13528
13964
|
}
|
|
13529
13965
|
if (node.computed) {
|
|
13530
|
-
return node.property.type ===
|
|
13966
|
+
return node.property.type === import_utils78.AST_NODE_TYPES.Literal && isPureReceiver(node.object);
|
|
13531
13967
|
}
|
|
13532
13968
|
return isPureReceiver(node.object);
|
|
13533
13969
|
default:
|
|
@@ -13535,7 +13971,7 @@ function isPureReceiver(node) {
|
|
|
13535
13971
|
}
|
|
13536
13972
|
}
|
|
13537
13973
|
function literalIndex(node) {
|
|
13538
|
-
if (node.type !==
|
|
13974
|
+
if (node.type !== import_utils78.AST_NODE_TYPES.Literal || typeof node.value !== "number") {
|
|
13539
13975
|
return null;
|
|
13540
13976
|
}
|
|
13541
13977
|
return Number.isInteger(node.value) && node.value >= 0 ? node.value : null;
|
|
@@ -13543,8 +13979,8 @@ function literalIndex(node) {
|
|
|
13543
13979
|
function propertyAccess(node) {
|
|
13544
13980
|
const path = [];
|
|
13545
13981
|
let current = node;
|
|
13546
|
-
while (current.type ===
|
|
13547
|
-
if (current.property.type !==
|
|
13982
|
+
while (current.type === import_utils78.AST_NODE_TYPES.MemberExpression && !current.computed && !current.optional) {
|
|
13983
|
+
if (current.property.type !== import_utils78.AST_NODE_TYPES.Identifier || COLLECTION_PROPERTIES.has(current.property.name) || LITERAL_KEY_HAZARDS.has(current.property.name)) return null;
|
|
13548
13984
|
path.unshift(current.property.name);
|
|
13549
13985
|
current = current.object;
|
|
13550
13986
|
}
|
|
@@ -13572,24 +14008,24 @@ var prefer_whole_object_assertion_default = createRule({
|
|
|
13572
14008
|
}
|
|
13573
14009
|
const { sourceCode } = context;
|
|
13574
14010
|
function parseAssertion(statement) {
|
|
13575
|
-
if (statement.type !==
|
|
14011
|
+
if (statement.type !== import_utils78.AST_NODE_TYPES.ExpressionStatement) {
|
|
13576
14012
|
return null;
|
|
13577
14013
|
}
|
|
13578
14014
|
const call = statement.expression;
|
|
13579
|
-
if (call.type !==
|
|
14015
|
+
if (call.type !== import_utils78.AST_NODE_TYPES.CallExpression) {
|
|
13580
14016
|
return null;
|
|
13581
14017
|
}
|
|
13582
14018
|
const callee = call.callee;
|
|
13583
|
-
if (callee.type !==
|
|
14019
|
+
if (callee.type !== import_utils78.AST_NODE_TYPES.MemberExpression || callee.computed || callee.property.type !== import_utils78.AST_NODE_TYPES.Identifier) {
|
|
13584
14020
|
return null;
|
|
13585
14021
|
}
|
|
13586
14022
|
const matcher = callee.property.name;
|
|
13587
14023
|
const expectCall = callee.object;
|
|
13588
|
-
if (expectCall.type !==
|
|
14024
|
+
if (expectCall.type !== import_utils78.AST_NODE_TYPES.CallExpression || expectCall.callee.type !== import_utils78.AST_NODE_TYPES.Identifier || expectCall.callee.name !== "expect" || expectCall.arguments.length !== 1) {
|
|
13589
14025
|
return null;
|
|
13590
14026
|
}
|
|
13591
14027
|
const actual = expectCall.arguments[0];
|
|
13592
|
-
if (actual === void 0 || actual.type !==
|
|
14028
|
+
if (actual === void 0 || actual.type !== import_utils78.AST_NODE_TYPES.MemberExpression || actual.optional) {
|
|
13593
14029
|
return null;
|
|
13594
14030
|
}
|
|
13595
14031
|
if (!isPureReceiver(actual.object)) {
|
|
@@ -13618,7 +14054,7 @@ var prefer_whole_object_assertion_default = createRule({
|
|
|
13618
14054
|
return null;
|
|
13619
14055
|
}
|
|
13620
14056
|
const expected = call.arguments[0];
|
|
13621
|
-
if (call.arguments.length !== 1 || expected === void 0 || expected.type ===
|
|
14057
|
+
if (call.arguments.length !== 1 || expected === void 0 || expected.type === import_utils78.AST_NODE_TYPES.SpreadElement) {
|
|
13622
14058
|
return null;
|
|
13623
14059
|
}
|
|
13624
14060
|
const literal = literalText(expected, (node) => sourceCode.getText(node));
|
|
@@ -13759,7 +14195,7 @@ var prefer_whole_object_assertion_default = createRule({
|
|
|
13759
14195
|
});
|
|
13760
14196
|
|
|
13761
14197
|
// src/rules/repeated-static-call-cases.ts
|
|
13762
|
-
var
|
|
14198
|
+
var import_utils79 = require("@typescript-eslint/utils");
|
|
13763
14199
|
var REPEATED_STATIC_CALL_CASES_DOCUMENTATION = {
|
|
13764
14200
|
summary: "Report three or more consecutive literal call assertions that should be independently named test cases.",
|
|
13765
14201
|
rationale: "Copy-pasted cases obscure the input table and stop later cases from being reported after the first failure.",
|
|
@@ -13780,67 +14216,67 @@ var EXPECT_MODIFIERS = /* @__PURE__ */ new Set(["not", "rejects", "resolves"]);
|
|
|
13780
14216
|
var SNAPSHOT_MATCHERS = /snapshot/iu;
|
|
13781
14217
|
var MIN_CASES2 = 3;
|
|
13782
14218
|
function staticMemberName5(node) {
|
|
13783
|
-
if (!node.computed && node.property.type ===
|
|
13784
|
-
if (node.computed && node.property.type ===
|
|
14219
|
+
if (!node.computed && node.property.type === import_utils79.AST_NODE_TYPES.Identifier) return node.property.name;
|
|
14220
|
+
if (node.computed && node.property.type === import_utils79.AST_NODE_TYPES.Literal && typeof node.property.value === "string") return node.property.value;
|
|
13785
14221
|
return null;
|
|
13786
14222
|
}
|
|
13787
|
-
function
|
|
13788
|
-
const variable =
|
|
14223
|
+
function importedName6(identifier, context, modules) {
|
|
14224
|
+
const variable = import_utils79.ASTUtils.findVariable(context.sourceCode.getScope(identifier), identifier.name);
|
|
13789
14225
|
if (variable === null || variable.defs.length === 0) return identifier.name;
|
|
13790
14226
|
for (const definition of variable.defs) {
|
|
13791
|
-
if (definition.node.type !==
|
|
14227
|
+
if (definition.node.type !== import_utils79.AST_NODE_TYPES.ImportSpecifier) continue;
|
|
13792
14228
|
const declaration = definition.node.parent;
|
|
13793
|
-
if (declaration.type !==
|
|
14229
|
+
if (declaration.type !== import_utils79.AST_NODE_TYPES.ImportDeclaration || typeof declaration.source.value !== "string" || !modules.has(declaration.source.value)) continue;
|
|
13794
14230
|
const imported = definition.node.imported;
|
|
13795
|
-
return imported.type ===
|
|
14231
|
+
return imported.type === import_utils79.AST_NODE_TYPES.Identifier ? imported.name : String(imported.value);
|
|
13796
14232
|
}
|
|
13797
14233
|
return null;
|
|
13798
14234
|
}
|
|
13799
14235
|
function isDirectTestCallback2(node, context) {
|
|
13800
|
-
if (node.type !==
|
|
14236
|
+
if (node.type !== import_utils79.AST_NODE_TYPES.ArrowFunctionExpression && node.type !== import_utils79.AST_NODE_TYPES.FunctionExpression) return false;
|
|
13801
14237
|
const call = node.parent;
|
|
13802
|
-
if (call?.type !==
|
|
14238
|
+
if (call?.type !== import_utils79.AST_NODE_TYPES.CallExpression || !call.arguments.includes(node)) return false;
|
|
13803
14239
|
const root = testRoot2(call.callee);
|
|
13804
|
-
return root !== null && TEST_NAMES2.has(
|
|
14240
|
+
return root !== null && TEST_NAMES2.has(importedName6(root, context, TEST_MODULES4) ?? "");
|
|
13805
14241
|
}
|
|
13806
14242
|
function testRoot2(callee) {
|
|
13807
|
-
if (callee.type ===
|
|
13808
|
-
if (callee.type !==
|
|
14243
|
+
if (callee.type === import_utils79.AST_NODE_TYPES.Identifier) return callee;
|
|
14244
|
+
if (callee.type !== import_utils79.AST_NODE_TYPES.MemberExpression) return null;
|
|
13809
14245
|
const modifier = staticMemberName5(callee);
|
|
13810
14246
|
return modifier !== null && TEST_MODIFIERS4.has(modifier) ? testRoot2(callee.object) : null;
|
|
13811
14247
|
}
|
|
13812
14248
|
function isStatic(node) {
|
|
13813
|
-
if (node.type ===
|
|
14249
|
+
if (node.type === import_utils79.AST_NODE_TYPES.TSAsExpression || node.type === import_utils79.AST_NODE_TYPES.TSTypeAssertion || node.type === import_utils79.AST_NODE_TYPES.TSSatisfiesExpression || node.type === import_utils79.AST_NODE_TYPES.TSNonNullExpression) return isStatic(node.expression);
|
|
13814
14250
|
switch (node.type) {
|
|
13815
|
-
case
|
|
14251
|
+
case import_utils79.AST_NODE_TYPES.Literal:
|
|
13816
14252
|
return true;
|
|
13817
|
-
case
|
|
14253
|
+
case import_utils79.AST_NODE_TYPES.TemplateLiteral:
|
|
13818
14254
|
return node.expressions.length === 0;
|
|
13819
|
-
case
|
|
14255
|
+
case import_utils79.AST_NODE_TYPES.UnaryExpression:
|
|
13820
14256
|
return (node.operator === "+" || node.operator === "-") && isStatic(node.argument);
|
|
13821
|
-
case
|
|
13822
|
-
return node.elements.every((item) => item !== null && item.type !==
|
|
13823
|
-
case
|
|
13824
|
-
return node.properties.every((property) => property.type ===
|
|
14257
|
+
case import_utils79.AST_NODE_TYPES.ArrayExpression:
|
|
14258
|
+
return node.elements.every((item) => item !== null && item.type !== import_utils79.AST_NODE_TYPES.SpreadElement && isStatic(item));
|
|
14259
|
+
case import_utils79.AST_NODE_TYPES.ObjectExpression:
|
|
14260
|
+
return node.properties.every((property) => property.type === import_utils79.AST_NODE_TYPES.Property && !property.computed && property.kind === "init" && property.value.type !== import_utils79.AST_NODE_TYPES.AssignmentPattern && isStatic(property.value));
|
|
13825
14261
|
default:
|
|
13826
14262
|
return false;
|
|
13827
14263
|
}
|
|
13828
14264
|
}
|
|
13829
14265
|
function staticShape(node) {
|
|
13830
|
-
if (node.type ===
|
|
14266
|
+
if (node.type === import_utils79.AST_NODE_TYPES.TSAsExpression || node.type === import_utils79.AST_NODE_TYPES.TSTypeAssertion || node.type === import_utils79.AST_NODE_TYPES.TSSatisfiesExpression || node.type === import_utils79.AST_NODE_TYPES.TSNonNullExpression) return staticShape(node.expression);
|
|
13831
14267
|
switch (node.type) {
|
|
13832
|
-
case
|
|
14268
|
+
case import_utils79.AST_NODE_TYPES.Literal:
|
|
13833
14269
|
return `literal:${typeof node.value}`;
|
|
13834
|
-
case
|
|
14270
|
+
case import_utils79.AST_NODE_TYPES.TemplateLiteral:
|
|
13835
14271
|
return "template";
|
|
13836
|
-
case
|
|
14272
|
+
case import_utils79.AST_NODE_TYPES.UnaryExpression:
|
|
13837
14273
|
return `unary:${node.operator}:${staticShape(node.argument)}`;
|
|
13838
|
-
case
|
|
13839
|
-
return `array(${node.elements.map((item) => item === null || item.type ===
|
|
13840
|
-
case
|
|
14274
|
+
case import_utils79.AST_NODE_TYPES.ArrayExpression:
|
|
14275
|
+
return `array(${node.elements.map((item) => item === null || item.type === import_utils79.AST_NODE_TYPES.SpreadElement ? "invalid" : staticShape(item)).join(",")})`;
|
|
14276
|
+
case import_utils79.AST_NODE_TYPES.ObjectExpression:
|
|
13841
14277
|
return `object(${node.properties.map((property) => {
|
|
13842
|
-
if (property.type !==
|
|
13843
|
-
const key = property.key.type ===
|
|
14278
|
+
if (property.type !== import_utils79.AST_NODE_TYPES.Property || property.computed || property.value.type === import_utils79.AST_NODE_TYPES.AssignmentPattern) return "invalid";
|
|
14279
|
+
const key = property.key.type === import_utils79.AST_NODE_TYPES.Identifier ? property.key.name : String(property.key.value);
|
|
13844
14280
|
return `${key}:${staticShape(property.value)}`;
|
|
13845
14281
|
}).join(",")})`;
|
|
13846
14282
|
default:
|
|
@@ -13848,16 +14284,16 @@ function staticShape(node) {
|
|
|
13848
14284
|
}
|
|
13849
14285
|
}
|
|
13850
14286
|
function assertionShape(statement, context) {
|
|
13851
|
-
if (statement.type !==
|
|
14287
|
+
if (statement.type !== import_utils79.AST_NODE_TYPES.ExpressionStatement || statement.expression.type !== import_utils79.AST_NODE_TYPES.CallExpression) return null;
|
|
13852
14288
|
const matcherCall = statement.expression;
|
|
13853
|
-
if (matcherCall.callee.type !==
|
|
14289
|
+
if (matcherCall.callee.type !== import_utils79.AST_NODE_TYPES.MemberExpression || matcherCall.callee.computed || matcherCall.callee.property.type !== import_utils79.AST_NODE_TYPES.Identifier || matcherCall.arguments.length !== 1) return null;
|
|
13854
14290
|
const matcher = matcherCall.callee.property.name;
|
|
13855
14291
|
if (SNAPSHOT_MATCHERS.test(matcher)) return null;
|
|
13856
14292
|
const chain = expectCallFromMatcher(matcherCall.callee);
|
|
13857
|
-
if (chain === null || chain.call.callee.type !==
|
|
14293
|
+
if (chain === null || chain.call.callee.type !== import_utils79.AST_NODE_TYPES.Identifier || importedName6(chain.call.callee, context, ASSERTION_MODULES3) !== "expect" || chain.call.arguments.length !== 1) return null;
|
|
13858
14294
|
const observed = chain.call.arguments[0];
|
|
13859
14295
|
const expected = matcherCall.arguments[0];
|
|
13860
|
-
if (observed?.type !==
|
|
14296
|
+
if (observed?.type !== import_utils79.AST_NODE_TYPES.CallExpression || observed.callee.type !== import_utils79.AST_NODE_TYPES.Identifier || observed.arguments.length === 0 || observed.arguments.some((arg) => arg.type === import_utils79.AST_NODE_TYPES.SpreadElement || !isStatic(arg)) || expected?.type === import_utils79.AST_NODE_TYPES.SpreadElement || expected === void 0 || !isStatic(expected)) return null;
|
|
13861
14297
|
const skeleton = `${observed.callee.name}/${observed.arguments.map((item) => staticShape(item)).join(",")}/${chain.modifiers.join(".")}/${matcher}/${staticShape(expected)}`;
|
|
13862
14298
|
const values = [...observed.arguments, expected].map((item) => context.sourceCode.getText(item)).join("\0");
|
|
13863
14299
|
return { statement, skeleton, values };
|
|
@@ -13865,13 +14301,13 @@ function assertionShape(statement, context) {
|
|
|
13865
14301
|
function expectCallFromMatcher(node) {
|
|
13866
14302
|
const modifiers = [];
|
|
13867
14303
|
let receiver = node.object;
|
|
13868
|
-
while (receiver.type ===
|
|
14304
|
+
while (receiver.type === import_utils79.AST_NODE_TYPES.MemberExpression) {
|
|
13869
14305
|
const modifier = staticMemberName5(receiver);
|
|
13870
14306
|
if (modifier === null || !EXPECT_MODIFIERS.has(modifier)) return null;
|
|
13871
14307
|
modifiers.unshift(modifier);
|
|
13872
14308
|
receiver = receiver.object;
|
|
13873
14309
|
}
|
|
13874
|
-
return receiver.type ===
|
|
14310
|
+
return receiver.type === import_utils79.AST_NODE_TYPES.CallExpression ? { call: receiver, modifiers } : null;
|
|
13875
14311
|
}
|
|
13876
14312
|
var repeated_static_call_cases_default = createRule({
|
|
13877
14313
|
name: "repeated-static-call-cases",
|
|
@@ -13891,7 +14327,7 @@ var repeated_static_call_cases_default = createRule({
|
|
|
13891
14327
|
return {
|
|
13892
14328
|
"CallExpression > ArrowFunctionExpression, CallExpression > FunctionExpression"(node) {
|
|
13893
14329
|
const call = node.parent;
|
|
13894
|
-
if (call?.type ===
|
|
14330
|
+
if (call?.type === import_utils79.AST_NODE_TYPES.CallExpression) {
|
|
13895
14331
|
const duplicate = duplicateTestBodyCandidate(call, sourceCode);
|
|
13896
14332
|
if (duplicate !== null && duplicate.body === node) {
|
|
13897
14333
|
const groups = duplicateGroups.get(duplicate.container) ?? /* @__PURE__ */ new Map();
|
|
@@ -13901,7 +14337,7 @@ var repeated_static_call_cases_default = createRule({
|
|
|
13901
14337
|
duplicateGroups.set(duplicate.container, groups);
|
|
13902
14338
|
}
|
|
13903
14339
|
}
|
|
13904
|
-
if (!isDirectTestCallback2(node, context) || node.body.type !==
|
|
14340
|
+
if (!isDirectTestCallback2(node, context) || node.body.type !== import_utils79.AST_NODE_TYPES.BlockStatement) return;
|
|
13905
14341
|
let run = [];
|
|
13906
14342
|
const flush = () => {
|
|
13907
14343
|
if (run.length >= MIN_CASES2 && new Set(run.map((item) => item.values)).size > 1) {
|
|
@@ -13942,7 +14378,7 @@ var repeated_static_call_cases_default = createRule({
|
|
|
13942
14378
|
});
|
|
13943
14379
|
|
|
13944
14380
|
// src/rules/prefer-zod-infer.ts
|
|
13945
|
-
var
|
|
14381
|
+
var import_utils80 = require("@typescript-eslint/utils");
|
|
13946
14382
|
var PREFER_ZOD_INFER_DOCUMENTATION = {
|
|
13947
14383
|
summary: "Derive a type from its Zod schema with `z.infer` instead of hand-writing a twin declaration beside it.",
|
|
13948
14384
|
rationale: "A derived type stays synchronized when the runtime schema changes.",
|
|
@@ -13995,47 +14431,47 @@ var ZOD_TYPE_CONSTRAINTS = /* @__PURE__ */ new Set([
|
|
|
13995
14431
|
"Schema"
|
|
13996
14432
|
]);
|
|
13997
14433
|
var LEAF_NODE_TYPES = {
|
|
13998
|
-
string: [
|
|
13999
|
-
email: [
|
|
14000
|
-
url: [
|
|
14001
|
-
uuid: [
|
|
14002
|
-
ulid: [
|
|
14003
|
-
cuid: [
|
|
14004
|
-
cuid2: [
|
|
14005
|
-
nanoid: [
|
|
14006
|
-
iso: [
|
|
14007
|
-
number: [
|
|
14008
|
-
int: [
|
|
14009
|
-
float32: [
|
|
14010
|
-
float64: [
|
|
14011
|
-
boolean: [
|
|
14012
|
-
bigint: [
|
|
14013
|
-
symbol: [
|
|
14014
|
-
any: [
|
|
14015
|
-
unknown: [
|
|
14016
|
-
never: [
|
|
14017
|
-
void: [
|
|
14018
|
-
null: [
|
|
14019
|
-
undefined: [
|
|
14020
|
-
literal: [
|
|
14021
|
-
date: [
|
|
14022
|
-
array: [
|
|
14023
|
-
tuple: [
|
|
14024
|
-
object: [
|
|
14025
|
-
strictObject: [
|
|
14026
|
-
looseObject: [
|
|
14027
|
-
record: [
|
|
14028
|
-
map: [
|
|
14029
|
-
set: [
|
|
14030
|
-
promise: [
|
|
14031
|
-
enum: [
|
|
14032
|
-
nativeEnum: [
|
|
14033
|
-
union: [
|
|
14034
|
-
discriminatedUnion: [
|
|
14035
|
-
intersection: [
|
|
14434
|
+
string: [import_utils80.AST_NODE_TYPES.TSStringKeyword],
|
|
14435
|
+
email: [import_utils80.AST_NODE_TYPES.TSStringKeyword],
|
|
14436
|
+
url: [import_utils80.AST_NODE_TYPES.TSStringKeyword],
|
|
14437
|
+
uuid: [import_utils80.AST_NODE_TYPES.TSStringKeyword],
|
|
14438
|
+
ulid: [import_utils80.AST_NODE_TYPES.TSStringKeyword],
|
|
14439
|
+
cuid: [import_utils80.AST_NODE_TYPES.TSStringKeyword],
|
|
14440
|
+
cuid2: [import_utils80.AST_NODE_TYPES.TSStringKeyword],
|
|
14441
|
+
nanoid: [import_utils80.AST_NODE_TYPES.TSStringKeyword],
|
|
14442
|
+
iso: [import_utils80.AST_NODE_TYPES.TSStringKeyword],
|
|
14443
|
+
number: [import_utils80.AST_NODE_TYPES.TSNumberKeyword],
|
|
14444
|
+
int: [import_utils80.AST_NODE_TYPES.TSNumberKeyword],
|
|
14445
|
+
float32: [import_utils80.AST_NODE_TYPES.TSNumberKeyword],
|
|
14446
|
+
float64: [import_utils80.AST_NODE_TYPES.TSNumberKeyword],
|
|
14447
|
+
boolean: [import_utils80.AST_NODE_TYPES.TSBooleanKeyword],
|
|
14448
|
+
bigint: [import_utils80.AST_NODE_TYPES.TSBigIntKeyword],
|
|
14449
|
+
symbol: [import_utils80.AST_NODE_TYPES.TSSymbolKeyword],
|
|
14450
|
+
any: [import_utils80.AST_NODE_TYPES.TSAnyKeyword],
|
|
14451
|
+
unknown: [import_utils80.AST_NODE_TYPES.TSUnknownKeyword],
|
|
14452
|
+
never: [import_utils80.AST_NODE_TYPES.TSNeverKeyword],
|
|
14453
|
+
void: [import_utils80.AST_NODE_TYPES.TSVoidKeyword],
|
|
14454
|
+
null: [import_utils80.AST_NODE_TYPES.TSNullKeyword],
|
|
14455
|
+
undefined: [import_utils80.AST_NODE_TYPES.TSUndefinedKeyword],
|
|
14456
|
+
literal: [import_utils80.AST_NODE_TYPES.TSLiteralType],
|
|
14457
|
+
date: [import_utils80.AST_NODE_TYPES.TSTypeReference],
|
|
14458
|
+
array: [import_utils80.AST_NODE_TYPES.TSArrayType, import_utils80.AST_NODE_TYPES.TSTypeReference],
|
|
14459
|
+
tuple: [import_utils80.AST_NODE_TYPES.TSTupleType],
|
|
14460
|
+
object: [import_utils80.AST_NODE_TYPES.TSTypeLiteral, import_utils80.AST_NODE_TYPES.TSTypeReference],
|
|
14461
|
+
strictObject: [import_utils80.AST_NODE_TYPES.TSTypeLiteral, import_utils80.AST_NODE_TYPES.TSTypeReference],
|
|
14462
|
+
looseObject: [import_utils80.AST_NODE_TYPES.TSTypeLiteral, import_utils80.AST_NODE_TYPES.TSTypeReference],
|
|
14463
|
+
record: [import_utils80.AST_NODE_TYPES.TSTypeReference, import_utils80.AST_NODE_TYPES.TSTypeLiteral],
|
|
14464
|
+
map: [import_utils80.AST_NODE_TYPES.TSTypeReference],
|
|
14465
|
+
set: [import_utils80.AST_NODE_TYPES.TSTypeReference],
|
|
14466
|
+
promise: [import_utils80.AST_NODE_TYPES.TSTypeReference],
|
|
14467
|
+
enum: [import_utils80.AST_NODE_TYPES.TSUnionType, import_utils80.AST_NODE_TYPES.TSTypeReference, import_utils80.AST_NODE_TYPES.TSLiteralType],
|
|
14468
|
+
nativeEnum: [import_utils80.AST_NODE_TYPES.TSUnionType, import_utils80.AST_NODE_TYPES.TSTypeReference, import_utils80.AST_NODE_TYPES.TSLiteralType],
|
|
14469
|
+
union: [import_utils80.AST_NODE_TYPES.TSUnionType, import_utils80.AST_NODE_TYPES.TSTypeReference],
|
|
14470
|
+
discriminatedUnion: [import_utils80.AST_NODE_TYPES.TSUnionType, import_utils80.AST_NODE_TYPES.TSTypeReference],
|
|
14471
|
+
intersection: [import_utils80.AST_NODE_TYPES.TSIntersectionType, import_utils80.AST_NODE_TYPES.TSTypeReference]
|
|
14036
14472
|
};
|
|
14037
14473
|
function primitiveLiteralKey(node) {
|
|
14038
|
-
if (node.type !==
|
|
14474
|
+
if (node.type !== import_utils80.AST_NODE_TYPES.Literal) {
|
|
14039
14475
|
return null;
|
|
14040
14476
|
}
|
|
14041
14477
|
if (node.value === null) {
|
|
@@ -14067,13 +14503,13 @@ function staticZodDomain(leaf, call) {
|
|
|
14067
14503
|
}
|
|
14068
14504
|
if (leaf === "literal") {
|
|
14069
14505
|
const [argument] = call.arguments;
|
|
14070
|
-
if (argument === void 0 || argument.type ===
|
|
14506
|
+
if (argument === void 0 || argument.type === import_utils80.AST_NODE_TYPES.SpreadElement) {
|
|
14071
14507
|
return null;
|
|
14072
14508
|
}
|
|
14073
|
-
if (argument.type ===
|
|
14509
|
+
if (argument.type === import_utils80.AST_NODE_TYPES.ArrayExpression) {
|
|
14074
14510
|
return exactDomain(
|
|
14075
14511
|
argument.elements.map(
|
|
14076
|
-
(element) => element === null || element.type ===
|
|
14512
|
+
(element) => element === null || element.type === import_utils80.AST_NODE_TYPES.SpreadElement ? null : primitiveLiteralKey(element)
|
|
14077
14513
|
)
|
|
14078
14514
|
);
|
|
14079
14515
|
}
|
|
@@ -14081,13 +14517,13 @@ function staticZodDomain(leaf, call) {
|
|
|
14081
14517
|
}
|
|
14082
14518
|
if (leaf === "enum") {
|
|
14083
14519
|
const [argument] = call.arguments;
|
|
14084
|
-
if (argument === void 0 || argument.type ===
|
|
14520
|
+
if (argument === void 0 || argument.type === import_utils80.AST_NODE_TYPES.SpreadElement) {
|
|
14085
14521
|
return null;
|
|
14086
14522
|
}
|
|
14087
|
-
if (argument.type ===
|
|
14523
|
+
if (argument.type === import_utils80.AST_NODE_TYPES.ArrayExpression) {
|
|
14088
14524
|
return exactDomain(
|
|
14089
14525
|
argument.elements.map((element) => {
|
|
14090
|
-
if (element === null || element.type ===
|
|
14526
|
+
if (element === null || element.type === import_utils80.AST_NODE_TYPES.SpreadElement) {
|
|
14091
14527
|
return null;
|
|
14092
14528
|
}
|
|
14093
14529
|
const key = primitiveLiteralKey(element);
|
|
@@ -14095,10 +14531,10 @@ function staticZodDomain(leaf, call) {
|
|
|
14095
14531
|
})
|
|
14096
14532
|
);
|
|
14097
14533
|
}
|
|
14098
|
-
if (argument.type ===
|
|
14534
|
+
if (argument.type === import_utils80.AST_NODE_TYPES.ObjectExpression) {
|
|
14099
14535
|
return exactDomain(
|
|
14100
14536
|
argument.properties.map((property) => {
|
|
14101
|
-
if (property.type !==
|
|
14537
|
+
if (property.type !== import_utils80.AST_NODE_TYPES.Property || property.computed || property.kind !== "init" || property.method || property.shorthand) {
|
|
14102
14538
|
return null;
|
|
14103
14539
|
}
|
|
14104
14540
|
const key = primitiveLiteralKey(property.value);
|
|
@@ -14125,15 +14561,15 @@ function sameDomain(left, right) {
|
|
|
14125
14561
|
return true;
|
|
14126
14562
|
}
|
|
14127
14563
|
function isExportedDeclaration(node) {
|
|
14128
|
-
return node.parent?.type ===
|
|
14564
|
+
return node.parent?.type === import_utils80.AST_NODE_TYPES.ExportNamedDeclaration;
|
|
14129
14565
|
}
|
|
14130
14566
|
function isModuleLevelConst(node) {
|
|
14131
14567
|
const declaration = node.parent;
|
|
14132
|
-
if (declaration.type !==
|
|
14568
|
+
if (declaration.type !== import_utils80.AST_NODE_TYPES.VariableDeclaration || declaration.kind !== "const") {
|
|
14133
14569
|
return false;
|
|
14134
14570
|
}
|
|
14135
14571
|
const container = declaration.parent;
|
|
14136
|
-
return container.type ===
|
|
14572
|
+
return container.type === import_utils80.AST_NODE_TYPES.Program || container.type === import_utils80.AST_NODE_TYPES.ExportNamedDeclaration && container.parent.type === import_utils80.AST_NODE_TYPES.Program;
|
|
14137
14573
|
}
|
|
14138
14574
|
function normalizeSchemaName(name) {
|
|
14139
14575
|
return name.replace(/Schema$/i, "").replace(/^Z(?=[A-Z])/, "").toLowerCase();
|
|
@@ -14142,20 +14578,20 @@ function normalizeTypeName(name) {
|
|
|
14142
14578
|
return name.replace(/Type$/, "").toLowerCase();
|
|
14143
14579
|
}
|
|
14144
14580
|
function unwrapNullish(annotation) {
|
|
14145
|
-
if (annotation.type !==
|
|
14581
|
+
if (annotation.type !== import_utils80.AST_NODE_TYPES.TSUnionType) {
|
|
14146
14582
|
return {
|
|
14147
14583
|
core: annotation,
|
|
14148
|
-
nullable: annotation.type ===
|
|
14584
|
+
nullable: annotation.type === import_utils80.AST_NODE_TYPES.TSNullKeyword
|
|
14149
14585
|
};
|
|
14150
14586
|
}
|
|
14151
14587
|
const rest = [];
|
|
14152
14588
|
let nullable = false;
|
|
14153
14589
|
for (const member of annotation.types) {
|
|
14154
|
-
if (member.type ===
|
|
14590
|
+
if (member.type === import_utils80.AST_NODE_TYPES.TSNullKeyword) {
|
|
14155
14591
|
nullable = true;
|
|
14156
14592
|
continue;
|
|
14157
14593
|
}
|
|
14158
|
-
if (member.type ===
|
|
14594
|
+
if (member.type === import_utils80.AST_NODE_TYPES.TSUndefinedKeyword) {
|
|
14159
14595
|
continue;
|
|
14160
14596
|
}
|
|
14161
14597
|
rest.push(member);
|
|
@@ -14189,18 +14625,18 @@ function leafAgrees(field, annotation) {
|
|
|
14189
14625
|
return null;
|
|
14190
14626
|
}
|
|
14191
14627
|
if (leaf === "date") {
|
|
14192
|
-
return core.type ===
|
|
14628
|
+
return core.type === import_utils80.AST_NODE_TYPES.TSTypeReference && core.typeName.type === import_utils80.AST_NODE_TYPES.Identifier && core.typeName.name === "Date";
|
|
14193
14629
|
}
|
|
14194
14630
|
return expected.includes(core.type);
|
|
14195
14631
|
}
|
|
14196
14632
|
function typeLiteralDomain(annotation) {
|
|
14197
|
-
const members = annotation.type ===
|
|
14633
|
+
const members = annotation.type === import_utils80.AST_NODE_TYPES.TSUnionType ? annotation.types : [annotation];
|
|
14198
14634
|
const keys = [];
|
|
14199
14635
|
for (const member of members) {
|
|
14200
|
-
if (member.type ===
|
|
14636
|
+
if (member.type === import_utils80.AST_NODE_TYPES.TSNullKeyword) {
|
|
14201
14637
|
continue;
|
|
14202
14638
|
}
|
|
14203
|
-
if (member.type !==
|
|
14639
|
+
if (member.type !== import_utils80.AST_NODE_TYPES.TSLiteralType) {
|
|
14204
14640
|
return null;
|
|
14205
14641
|
}
|
|
14206
14642
|
keys.push(primitiveLiteralKey(member.literal));
|
|
@@ -14208,11 +14644,11 @@ function typeLiteralDomain(annotation) {
|
|
|
14208
14644
|
return exactDomain(keys);
|
|
14209
14645
|
}
|
|
14210
14646
|
function staticStringUnionDomain(node) {
|
|
14211
|
-
if (node.type !==
|
|
14647
|
+
if (node.type !== import_utils80.AST_NODE_TYPES.TSUnionType) {
|
|
14212
14648
|
return null;
|
|
14213
14649
|
}
|
|
14214
14650
|
const keys = node.types.map((member) => {
|
|
14215
|
-
if (member.type !==
|
|
14651
|
+
if (member.type !== import_utils80.AST_NODE_TYPES.TSLiteralType) {
|
|
14216
14652
|
return null;
|
|
14217
14653
|
}
|
|
14218
14654
|
const key = primitiveLiteralKey(member.literal);
|
|
@@ -14280,14 +14716,14 @@ var prefer_zod_infer_default = createRule({
|
|
|
14280
14716
|
function zodCallChain(node) {
|
|
14281
14717
|
const chain = [];
|
|
14282
14718
|
let current = node;
|
|
14283
|
-
while (current.type ===
|
|
14719
|
+
while (current.type === import_utils80.AST_NODE_TYPES.CallExpression) {
|
|
14284
14720
|
const callee = current.callee;
|
|
14285
|
-
if (callee.type !==
|
|
14721
|
+
if (callee.type !== import_utils80.AST_NODE_TYPES.MemberExpression || callee.computed || callee.property.type !== import_utils80.AST_NODE_TYPES.Identifier) {
|
|
14286
14722
|
return null;
|
|
14287
14723
|
}
|
|
14288
14724
|
chain.push(current);
|
|
14289
14725
|
const receiver = callee.object;
|
|
14290
|
-
if (receiver.type ===
|
|
14726
|
+
if (receiver.type === import_utils80.AST_NODE_TYPES.Identifier) {
|
|
14291
14727
|
return zodNamespaces.has(receiver.name) ? chain.reverse() : null;
|
|
14292
14728
|
}
|
|
14293
14729
|
current = receiver;
|
|
@@ -14296,14 +14732,14 @@ var prefer_zod_infer_default = createRule({
|
|
|
14296
14732
|
}
|
|
14297
14733
|
function methodName2(call) {
|
|
14298
14734
|
const callee = call.callee;
|
|
14299
|
-
return callee.type ===
|
|
14735
|
+
return callee.type === import_utils80.AST_NODE_TYPES.MemberExpression && callee.property.type === import_utils80.AST_NODE_TYPES.Identifier ? callee.property.name : "";
|
|
14300
14736
|
}
|
|
14301
14737
|
function recordZodImport(node) {
|
|
14302
14738
|
if (!isZodModule(node.source.value)) {
|
|
14303
14739
|
return;
|
|
14304
14740
|
}
|
|
14305
14741
|
for (const specifier of node.specifiers) {
|
|
14306
|
-
if (specifier.type ===
|
|
14742
|
+
if (specifier.type === import_utils80.AST_NODE_TYPES.ImportNamespaceSpecifier || specifier.type === import_utils80.AST_NODE_TYPES.ImportDefaultSpecifier || specifier.type === import_utils80.AST_NODE_TYPES.ImportSpecifier && specifier.imported.type === import_utils80.AST_NODE_TYPES.Identifier && specifier.imported.name === "z") {
|
|
14307
14743
|
zodNamespaces.add(specifier.local.name);
|
|
14308
14744
|
}
|
|
14309
14745
|
}
|
|
@@ -14313,13 +14749,13 @@ var prefer_zod_infer_default = createRule({
|
|
|
14313
14749
|
let current = node;
|
|
14314
14750
|
let leaf = null;
|
|
14315
14751
|
let leafCall = null;
|
|
14316
|
-
while (current.type ===
|
|
14752
|
+
while (current.type === import_utils80.AST_NODE_TYPES.CallExpression) {
|
|
14317
14753
|
const callee = current.callee;
|
|
14318
|
-
if (callee.type !==
|
|
14754
|
+
if (callee.type !== import_utils80.AST_NODE_TYPES.MemberExpression || callee.computed || callee.property.type !== import_utils80.AST_NODE_TYPES.Identifier) {
|
|
14319
14755
|
break;
|
|
14320
14756
|
}
|
|
14321
14757
|
const receiver = callee.object;
|
|
14322
|
-
if (receiver.type ===
|
|
14758
|
+
if (receiver.type === import_utils80.AST_NODE_TYPES.Identifier && zodNamespaces.has(receiver.name)) {
|
|
14323
14759
|
leaf = callee.property.name;
|
|
14324
14760
|
leafCall = current;
|
|
14325
14761
|
break;
|
|
@@ -14350,30 +14786,30 @@ var prefer_zod_infer_default = createRule({
|
|
|
14350
14786
|
return domain instanceof Set && domain.size >= 2 ? domain : null;
|
|
14351
14787
|
}
|
|
14352
14788
|
function inferredSchemaName(node) {
|
|
14353
|
-
if (node.type !==
|
|
14789
|
+
if (node.type !== import_utils80.AST_NODE_TYPES.TSTypeReference || node.typeName.type !== import_utils80.AST_NODE_TYPES.TSQualifiedName || node.typeName.left.type !== import_utils80.AST_NODE_TYPES.Identifier || !zodNamespaces.has(node.typeName.left.name) || node.typeName.right.name !== "infer") {
|
|
14354
14790
|
return null;
|
|
14355
14791
|
}
|
|
14356
14792
|
const arguments_ = node.typeArguments?.params ?? [];
|
|
14357
14793
|
const [argument] = arguments_;
|
|
14358
|
-
return arguments_.length === 1 && argument?.type ===
|
|
14794
|
+
return arguments_.length === 1 && argument?.type === import_utils80.AST_NODE_TYPES.TSTypeQuery && argument.exprName.type === import_utils80.AST_NODE_TYPES.Identifier ? argument.exprName.name : null;
|
|
14359
14795
|
}
|
|
14360
14796
|
function recordLiteralUnions(members, owner, ownerName, exported) {
|
|
14361
14797
|
for (const member of members) {
|
|
14362
|
-
if (member.type !==
|
|
14798
|
+
if (member.type !== import_utils80.AST_NODE_TYPES.TSPropertySignature || member.computed || member.optional || member.readonly || member.typeAnnotation === void 0) {
|
|
14363
14799
|
continue;
|
|
14364
14800
|
}
|
|
14365
14801
|
const key = member.key;
|
|
14366
|
-
const
|
|
14367
|
-
if (
|
|
14802
|
+
const propertyName7 = key.type === import_utils80.AST_NODE_TYPES.Identifier ? key.name : key.type === import_utils80.AST_NODE_TYPES.Literal && typeof key.value === "string" ? key.value : null;
|
|
14803
|
+
if (propertyName7 === null) {
|
|
14368
14804
|
continue;
|
|
14369
14805
|
}
|
|
14370
|
-
const propertyTokens = nameTokens(
|
|
14806
|
+
const propertyTokens = nameTokens(propertyName7);
|
|
14371
14807
|
if (propertyTokens.length < 2) {
|
|
14372
14808
|
continue;
|
|
14373
14809
|
}
|
|
14374
14810
|
const annotation = member.typeAnnotation.typeAnnotation;
|
|
14375
14811
|
const domain = staticStringUnionDomain(annotation);
|
|
14376
|
-
if (domain === null || annotation.type !==
|
|
14812
|
+
if (domain === null || annotation.type !== import_utils80.AST_NODE_TYPES.TSUnionType) {
|
|
14377
14813
|
continue;
|
|
14378
14814
|
}
|
|
14379
14815
|
literalUnionOccurrences.push({
|
|
@@ -14382,7 +14818,7 @@ var prefer_zod_infer_default = createRule({
|
|
|
14382
14818
|
node: annotation,
|
|
14383
14819
|
owner,
|
|
14384
14820
|
ownerName,
|
|
14385
|
-
propertyName:
|
|
14821
|
+
propertyName: propertyName7,
|
|
14386
14822
|
propertyTokens
|
|
14387
14823
|
});
|
|
14388
14824
|
}
|
|
@@ -14404,16 +14840,16 @@ var prefer_zod_infer_default = createRule({
|
|
|
14404
14840
|
return null;
|
|
14405
14841
|
}
|
|
14406
14842
|
const shape = base.arguments[0];
|
|
14407
|
-
if (shape === void 0 || shape.type !==
|
|
14843
|
+
if (shape === void 0 || shape.type !== import_utils80.AST_NODE_TYPES.ObjectExpression) {
|
|
14408
14844
|
return null;
|
|
14409
14845
|
}
|
|
14410
14846
|
const fields = /* @__PURE__ */ new Map();
|
|
14411
14847
|
for (const property of shape.properties) {
|
|
14412
|
-
if (property.type !==
|
|
14848
|
+
if (property.type !== import_utils80.AST_NODE_TYPES.Property || property.computed) {
|
|
14413
14849
|
return null;
|
|
14414
14850
|
}
|
|
14415
14851
|
const { key } = property;
|
|
14416
|
-
const name = key.type ===
|
|
14852
|
+
const name = key.type === import_utils80.AST_NODE_TYPES.Identifier ? key.name : key.type === import_utils80.AST_NODE_TYPES.Literal && typeof key.value === "string" ? key.value : null;
|
|
14417
14853
|
if (name === null) {
|
|
14418
14854
|
return null;
|
|
14419
14855
|
}
|
|
@@ -14424,11 +14860,11 @@ var prefer_zod_infer_default = createRule({
|
|
|
14424
14860
|
function typeMembers(members) {
|
|
14425
14861
|
const result = /* @__PURE__ */ new Map();
|
|
14426
14862
|
for (const member of members) {
|
|
14427
|
-
if (member.type !==
|
|
14863
|
+
if (member.type !== import_utils80.AST_NODE_TYPES.TSPropertySignature || member.computed) {
|
|
14428
14864
|
return null;
|
|
14429
14865
|
}
|
|
14430
14866
|
const { key } = member;
|
|
14431
|
-
const name = key.type ===
|
|
14867
|
+
const name = key.type === import_utils80.AST_NODE_TYPES.Identifier ? key.name : key.type === import_utils80.AST_NODE_TYPES.Literal && typeof key.value === "string" ? key.value : null;
|
|
14432
14868
|
if (name === null) {
|
|
14433
14869
|
return null;
|
|
14434
14870
|
}
|
|
@@ -14443,8 +14879,8 @@ var prefer_zod_infer_default = createRule({
|
|
|
14443
14879
|
return result.size === 0 ? null : result;
|
|
14444
14880
|
}
|
|
14445
14881
|
function collectConstrainedNames(node) {
|
|
14446
|
-
if (node.type ===
|
|
14447
|
-
if (node.typeName.type ===
|
|
14882
|
+
if (node.type === import_utils80.AST_NODE_TYPES.TSTypeReference) {
|
|
14883
|
+
if (node.typeName.type === import_utils80.AST_NODE_TYPES.Identifier) {
|
|
14448
14884
|
constrainedTypeNames.add(node.typeName.name);
|
|
14449
14885
|
}
|
|
14450
14886
|
for (const argument of node.typeArguments?.params ?? []) {
|
|
@@ -14452,11 +14888,11 @@ var prefer_zod_infer_default = createRule({
|
|
|
14452
14888
|
}
|
|
14453
14889
|
return;
|
|
14454
14890
|
}
|
|
14455
|
-
if (node.type ===
|
|
14891
|
+
if (node.type === import_utils80.AST_NODE_TYPES.TSArrayType) {
|
|
14456
14892
|
collectConstrainedNames(node.elementType);
|
|
14457
14893
|
return;
|
|
14458
14894
|
}
|
|
14459
|
-
if (node.type ===
|
|
14895
|
+
if (node.type === import_utils80.AST_NODE_TYPES.TSUnionType || node.type === import_utils80.AST_NODE_TYPES.TSIntersectionType) {
|
|
14460
14896
|
for (const member of node.types) {
|
|
14461
14897
|
collectConstrainedNames(member);
|
|
14462
14898
|
}
|
|
@@ -14500,7 +14936,7 @@ var prefer_zod_infer_default = createRule({
|
|
|
14500
14936
|
return {
|
|
14501
14937
|
Program(node) {
|
|
14502
14938
|
for (const statement of node.body) {
|
|
14503
|
-
if (statement.type ===
|
|
14939
|
+
if (statement.type === import_utils80.AST_NODE_TYPES.ImportDeclaration) {
|
|
14504
14940
|
recordZodImport(statement);
|
|
14505
14941
|
}
|
|
14506
14942
|
}
|
|
@@ -14509,7 +14945,7 @@ var prefer_zod_infer_default = createRule({
|
|
|
14509
14945
|
recordZodImport(node);
|
|
14510
14946
|
},
|
|
14511
14947
|
VariableDeclarator(node) {
|
|
14512
|
-
if (node.id.type !==
|
|
14948
|
+
if (node.id.type !== import_utils80.AST_NODE_TYPES.Identifier || node.init == null) {
|
|
14513
14949
|
return;
|
|
14514
14950
|
}
|
|
14515
14951
|
const fields = schemaFields(node.init);
|
|
@@ -14526,14 +14962,14 @@ var prefer_zod_infer_default = createRule({
|
|
|
14526
14962
|
},
|
|
14527
14963
|
/** Records `XSchema.transform(...)` and equivalent module-level reshaping. */
|
|
14528
14964
|
"MemberExpression[computed=false]"(node) {
|
|
14529
|
-
if (node.object.type ===
|
|
14965
|
+
if (node.object.type === import_utils80.AST_NODE_TYPES.Identifier && node.property.type === import_utils80.AST_NODE_TYPES.Identifier && MODULE_LEVEL_RESHAPERS.has(node.property.name)) {
|
|
14530
14966
|
reshapedSchemaNames.add(node.object.name);
|
|
14531
14967
|
}
|
|
14532
14968
|
},
|
|
14533
14969
|
/** Records every type argument carried by a Zod constraint. */
|
|
14534
14970
|
TSTypeReference(node) {
|
|
14535
14971
|
const { typeName } = node;
|
|
14536
|
-
const referenced = typeName.type ===
|
|
14972
|
+
const referenced = typeName.type === import_utils80.AST_NODE_TYPES.Identifier ? typeName.name : typeName.type === import_utils80.AST_NODE_TYPES.TSQualifiedName && typeName.right.type === import_utils80.AST_NODE_TYPES.Identifier ? typeName.right.name : null;
|
|
14537
14973
|
if (referenced === null || !ZOD_TYPE_CONSTRAINTS.has(referenced)) {
|
|
14538
14974
|
return;
|
|
14539
14975
|
}
|
|
@@ -14565,7 +15001,7 @@ var prefer_zod_infer_default = createRule({
|
|
|
14565
15001
|
typeName: node.id.name
|
|
14566
15002
|
});
|
|
14567
15003
|
}
|
|
14568
|
-
if (node.typeParameters !== void 0 || node.typeAnnotation.type !==
|
|
15004
|
+
if (node.typeParameters !== void 0 || node.typeAnnotation.type !== import_utils80.AST_NODE_TYPES.TSTypeLiteral) {
|
|
14569
15005
|
return;
|
|
14570
15006
|
}
|
|
14571
15007
|
const members = typeMembers(node.typeAnnotation.members);
|
|
@@ -14664,7 +15100,7 @@ var prefer_zod_infer_default = createRule({
|
|
|
14664
15100
|
});
|
|
14665
15101
|
|
|
14666
15102
|
// src/rules/require-assert-never.ts
|
|
14667
|
-
var
|
|
15103
|
+
var import_utils81 = require("@typescript-eslint/utils");
|
|
14668
15104
|
var import_typescript2 = __toESM(require("typescript"), 1);
|
|
14669
15105
|
var REQUIRE_ASSERT_NEVER_DOCUMENTATION = {
|
|
14670
15106
|
summary: "Require an empty switch default to call `assertNever` so discriminated unions remain exhaustive at compile time.",
|
|
@@ -14677,14 +15113,14 @@ var REQUIRE_ASSERT_NEVER_DOCUMENTATION = {
|
|
|
14677
15113
|
]
|
|
14678
15114
|
};
|
|
14679
15115
|
var isRuntimeHandlingStatement = (statement) => {
|
|
14680
|
-
if (statement.type ===
|
|
14681
|
-
if (statement.type ===
|
|
15116
|
+
if (statement.type === import_utils81.AST_NODE_TYPES.EmptyStatement) return false;
|
|
15117
|
+
if (statement.type === import_utils81.AST_NODE_TYPES.BreakStatement) {
|
|
14682
15118
|
return statement.label !== null;
|
|
14683
15119
|
}
|
|
14684
|
-
if (statement.type ===
|
|
15120
|
+
if (statement.type === import_utils81.AST_NODE_TYPES.TSTypeAliasDeclaration || statement.type === import_utils81.AST_NODE_TYPES.TSInterfaceDeclaration) {
|
|
14685
15121
|
return false;
|
|
14686
15122
|
}
|
|
14687
|
-
if (statement.type ===
|
|
15123
|
+
if (statement.type === import_utils81.AST_NODE_TYPES.BlockStatement) {
|
|
14688
15124
|
return statement.body.some(isRuntimeHandlingStatement);
|
|
14689
15125
|
}
|
|
14690
15126
|
return true;
|
|
@@ -14700,7 +15136,7 @@ var isCommentOnlyNoopDefault = (defaultCase, sourceCode) => {
|
|
|
14700
15136
|
return colonToken !== null && sourceCode.getCommentsAfter(colonToken).length > 0;
|
|
14701
15137
|
}
|
|
14702
15138
|
const only = defaultCase.consequent[0];
|
|
14703
|
-
if (only !== void 0 && defaultCase.consequent.length === 1 && only.type ===
|
|
15139
|
+
if (only !== void 0 && defaultCase.consequent.length === 1 && only.type === import_utils81.AST_NODE_TYPES.BlockStatement && !only.body.some(isRuntimeHandlingStatement)) {
|
|
14704
15140
|
return sourceCode.getCommentsInside(only).length > 0;
|
|
14705
15141
|
}
|
|
14706
15142
|
return false;
|
|
@@ -14756,7 +15192,7 @@ var require_assert_never_default = createRule({
|
|
|
14756
15192
|
create(context) {
|
|
14757
15193
|
let services;
|
|
14758
15194
|
try {
|
|
14759
|
-
services =
|
|
15195
|
+
services = import_utils81.ESLintUtils.getParserServices(context);
|
|
14760
15196
|
} catch {
|
|
14761
15197
|
services = null;
|
|
14762
15198
|
}
|
|
@@ -14783,7 +15219,7 @@ var require_assert_never_default = createRule({
|
|
|
14783
15219
|
});
|
|
14784
15220
|
|
|
14785
15221
|
// src/rules/require-fetch-timeout.ts
|
|
14786
|
-
var
|
|
15222
|
+
var import_utils82 = require("@typescript-eslint/utils");
|
|
14787
15223
|
var REQUIRE_FETCH_TIMEOUT_DOCUMENTATION = {
|
|
14788
15224
|
summary: "Require an abort `signal` (e.g. `AbortSignal.timeout(ms)`) on global `fetch()` calls so stalled upstreams cannot hang the caller forever.",
|
|
14789
15225
|
rationale: "An unbounded request can occupy work indefinitely when an upstream stalls.",
|
|
@@ -14809,14 +15245,14 @@ function matchesAnyPattern3(filename, patterns) {
|
|
|
14809
15245
|
return false;
|
|
14810
15246
|
}
|
|
14811
15247
|
function initProvablyLacksSignal(init) {
|
|
14812
|
-
if (init.type !==
|
|
15248
|
+
if (init.type !== import_utils82.AST_NODE_TYPES.ObjectExpression) {
|
|
14813
15249
|
return false;
|
|
14814
15250
|
}
|
|
14815
15251
|
for (const prop of init.properties) {
|
|
14816
|
-
if (prop.type ===
|
|
15252
|
+
if (prop.type === import_utils82.AST_NODE_TYPES.SpreadElement) {
|
|
14817
15253
|
return false;
|
|
14818
15254
|
}
|
|
14819
|
-
if (prop.key.type ===
|
|
15255
|
+
if (prop.key.type === import_utils82.AST_NODE_TYPES.Identifier && prop.key.name === "signal" || prop.key.type === import_utils82.AST_NODE_TYPES.Literal && prop.key.value === "signal") {
|
|
14820
15256
|
return false;
|
|
14821
15257
|
}
|
|
14822
15258
|
if (prop.computed) {
|
|
@@ -14826,7 +15262,7 @@ function initProvablyLacksSignal(init) {
|
|
|
14826
15262
|
return true;
|
|
14827
15263
|
}
|
|
14828
15264
|
function isInlineUrl(node, resolvesToGlobal) {
|
|
14829
|
-
return node.type ===
|
|
15265
|
+
return node.type === import_utils82.AST_NODE_TYPES.Literal && typeof node.value === "string" || node.type === import_utils82.AST_NODE_TYPES.TemplateLiteral || node.type === import_utils82.AST_NODE_TYPES.NewExpression && node.callee.type === import_utils82.AST_NODE_TYPES.Identifier && node.callee.name === "URL" && resolvesToGlobal(node.callee);
|
|
14830
15266
|
}
|
|
14831
15267
|
var require_fetch_timeout_default = createRule({
|
|
14832
15268
|
name: "require-fetch-timeout",
|
|
@@ -14864,30 +15300,30 @@ var require_fetch_timeout_default = createRule({
|
|
|
14864
15300
|
}
|
|
14865
15301
|
function resolvesToGlobal(identifier) {
|
|
14866
15302
|
const scope = context.sourceCode.getScope(identifier);
|
|
14867
|
-
const variable =
|
|
15303
|
+
const variable = import_utils82.ASTUtils.findVariable(scope, identifier.name);
|
|
14868
15304
|
return variable === null || variable.defs.length === 0;
|
|
14869
15305
|
}
|
|
14870
15306
|
function isGlobalFetchCall2(callee) {
|
|
14871
|
-
if (callee.type ===
|
|
15307
|
+
if (callee.type === import_utils82.AST_NODE_TYPES.Identifier) {
|
|
14872
15308
|
return callee.name === "fetch" && resolvesToGlobal(callee);
|
|
14873
15309
|
}
|
|
14874
|
-
return callee.type ===
|
|
15310
|
+
return callee.type === import_utils82.AST_NODE_TYPES.MemberExpression && !callee.computed && callee.property.type === import_utils82.AST_NODE_TYPES.Identifier && callee.property.name === "fetch" && callee.object.type === import_utils82.AST_NODE_TYPES.Identifier && GLOBAL_OBJECTS2.has(callee.object.name) && resolvesToGlobal(callee.object);
|
|
14875
15311
|
}
|
|
14876
15312
|
function localConstInitProvablyLacksSignal(identifier) {
|
|
14877
|
-
const variable =
|
|
15313
|
+
const variable = import_utils82.ASTUtils.findVariable(
|
|
14878
15314
|
context.sourceCode.getScope(identifier),
|
|
14879
15315
|
identifier.name
|
|
14880
15316
|
);
|
|
14881
15317
|
if (variable?.defs.length !== 1) return false;
|
|
14882
15318
|
const definition = variable.defs[0];
|
|
14883
|
-
if (definition?.type !== "Variable" || definition.parent.kind !== "const" || definition.node.init?.type !==
|
|
15319
|
+
if (definition?.type !== "Variable" || definition.parent.kind !== "const" || definition.node.init?.type !== import_utils82.AST_NODE_TYPES.ObjectExpression || !initProvablyLacksSignal(definition.node.init)) {
|
|
14884
15320
|
return false;
|
|
14885
15321
|
}
|
|
14886
15322
|
for (const reference of variable.references) {
|
|
14887
15323
|
const ref = reference.identifier;
|
|
14888
15324
|
if (ref === identifier || ref === definition.name) continue;
|
|
14889
15325
|
const member = ref.parent;
|
|
14890
|
-
if (member.type !==
|
|
15326
|
+
if (member.type !== import_utils82.AST_NODE_TYPES.MemberExpression || member.object !== ref || member.computed || member.property.type !== import_utils82.AST_NODE_TYPES.Identifier || member.property.name === "signal" || member.parent.type !== import_utils82.AST_NODE_TYPES.AssignmentExpression || member.parent.left !== member) {
|
|
14891
15327
|
return false;
|
|
14892
15328
|
}
|
|
14893
15329
|
}
|
|
@@ -14902,7 +15338,7 @@ var require_fetch_timeout_default = createRule({
|
|
|
14902
15338
|
if (node.arguments.length === 1 && first !== void 0 && !isInlineUrl(first, resolvesToGlobal)) {
|
|
14903
15339
|
return;
|
|
14904
15340
|
}
|
|
14905
|
-
if (init === void 0 || initProvablyLacksSignal(init) || init.type ===
|
|
15341
|
+
if (init === void 0 || initProvablyLacksSignal(init) || init.type === import_utils82.AST_NODE_TYPES.Identifier && localConstInitProvablyLacksSignal(init)) {
|
|
14906
15342
|
context.report({ node, messageId: "missingSignal" });
|
|
14907
15343
|
}
|
|
14908
15344
|
}
|
|
@@ -14910,8 +15346,141 @@ var require_fetch_timeout_default = createRule({
|
|
|
14910
15346
|
}
|
|
14911
15347
|
});
|
|
14912
15348
|
|
|
15349
|
+
// src/rules/require-interface-for-exported-class.ts
|
|
15350
|
+
var import_utils83 = require("@typescript-eslint/utils");
|
|
15351
|
+
var REQUIRE_INTERFACE_FOR_EXPORTED_CLASS_DOCUMENTATION = {
|
|
15352
|
+
summary: "Require exported concrete classes with public behavior to declare a contract.",
|
|
15353
|
+
rationale: "Consumers coupled only to a concrete class cannot substitute implementations or state the supported public capability independently of implementation details.",
|
|
15354
|
+
remediation: "Declare a focused interface and add an implements clause, or inherit from an intentional base contract.",
|
|
15355
|
+
category: "architecture",
|
|
15356
|
+
limitations: [
|
|
15357
|
+
"The warning-stage rule checks module-level class declarations and direct class-expression values exported directly, through local export specifiers, or through a default identifier; re-exports and expressions wrapped in other calls require review.",
|
|
15358
|
+
"An extends clause satisfies the contract only when its target is a locally declared abstract class; imported base-class contracts require an explicit implements clause.",
|
|
15359
|
+
"Static factories and data-only classes without public instance methods are outside the contract requirement."
|
|
15360
|
+
],
|
|
15361
|
+
examples: [
|
|
15362
|
+
{
|
|
15363
|
+
id: "implemented-store-contract",
|
|
15364
|
+
title: "Export behavior through a focused contract",
|
|
15365
|
+
outcome: "no-match",
|
|
15366
|
+
files: [
|
|
15367
|
+
{
|
|
15368
|
+
path: "src/artifact-store.ts",
|
|
15369
|
+
source: "export interface ArtifactStorage { read(id: string): Promise<Uint8Array>; } export class ArtifactStore implements ArtifactStorage { async read(id: string) { return new Uint8Array(); } }"
|
|
15370
|
+
}
|
|
15371
|
+
],
|
|
15372
|
+
focusPath: "src/artifact-store.ts",
|
|
15373
|
+
expectedCount: 0,
|
|
15374
|
+
public: true
|
|
15375
|
+
},
|
|
15376
|
+
{
|
|
15377
|
+
id: "concrete-only-store",
|
|
15378
|
+
title: "Do not export behavior only through a concrete class",
|
|
15379
|
+
outcome: "match",
|
|
15380
|
+
files: [
|
|
15381
|
+
{
|
|
15382
|
+
path: "src/artifact-store.ts",
|
|
15383
|
+
source: "export class ArtifactStore { async read(id: string) { return new Uint8Array(); } }"
|
|
15384
|
+
}
|
|
15385
|
+
],
|
|
15386
|
+
focusPath: "src/artifact-store.ts",
|
|
15387
|
+
expectedCount: 1,
|
|
15388
|
+
public: true
|
|
15389
|
+
}
|
|
15390
|
+
]
|
|
15391
|
+
};
|
|
15392
|
+
function hasPublicInstanceBehavior(node) {
|
|
15393
|
+
return node.body.body.some((member) => {
|
|
15394
|
+
if (member.type === import_utils83.AST_NODE_TYPES.MethodDefinition) {
|
|
15395
|
+
return member.kind !== "constructor" && !member.static && member.accessibility !== "private" && member.accessibility !== "protected" && member.key.type !== import_utils83.AST_NODE_TYPES.PrivateIdentifier;
|
|
15396
|
+
}
|
|
15397
|
+
if (member.type !== import_utils83.AST_NODE_TYPES.PropertyDefinition || member.static)
|
|
15398
|
+
return false;
|
|
15399
|
+
if (member.accessibility === "private" || member.accessibility === "protected" || member.key.type === import_utils83.AST_NODE_TYPES.PrivateIdentifier) return false;
|
|
15400
|
+
return member.value?.type === import_utils83.AST_NODE_TYPES.ArrowFunctionExpression || member.value?.type === import_utils83.AST_NODE_TYPES.FunctionExpression || member.typeAnnotation?.typeAnnotation.type === import_utils83.AST_NODE_TYPES.TSFunctionType;
|
|
15401
|
+
});
|
|
15402
|
+
}
|
|
15403
|
+
function classBindings(statement) {
|
|
15404
|
+
const declaration = statement.type === import_utils83.AST_NODE_TYPES.ExportNamedDeclaration ? statement.declaration : statement;
|
|
15405
|
+
if (declaration?.type === import_utils83.AST_NODE_TYPES.ClassDeclaration) {
|
|
15406
|
+
return declaration.id === null ? [] : [{ declaration, name: declaration.id.name }];
|
|
15407
|
+
}
|
|
15408
|
+
if (declaration?.type !== import_utils83.AST_NODE_TYPES.VariableDeclaration) return [];
|
|
15409
|
+
return declaration.declarations.flatMap(
|
|
15410
|
+
(item) => item.id.type === import_utils83.AST_NODE_TYPES.Identifier && item.init?.type === import_utils83.AST_NODE_TYPES.ClassExpression ? [{ declaration: item.init, name: item.id.name }] : []
|
|
15411
|
+
);
|
|
15412
|
+
}
|
|
15413
|
+
var require_interface_for_exported_class_default = createRule({
|
|
15414
|
+
name: "require-interface-for-exported-class",
|
|
15415
|
+
documentation: REQUIRE_INTERFACE_FOR_EXPORTED_CLASS_DOCUMENTATION,
|
|
15416
|
+
meta: {
|
|
15417
|
+
type: "suggestion",
|
|
15418
|
+
docs: {
|
|
15419
|
+
description: "Require exported concrete classes with public behavior to declare a contract."
|
|
15420
|
+
},
|
|
15421
|
+
schema: [],
|
|
15422
|
+
messages: {
|
|
15423
|
+
requireContract: "Exported class `{{name}}` has public behavior but no declared interface or base contract; add a focused contract and implement it."
|
|
15424
|
+
}
|
|
15425
|
+
},
|
|
15426
|
+
defaultOptions: [],
|
|
15427
|
+
create(context) {
|
|
15428
|
+
if (isTestFile(context.filename) || isStoryFile(context.filename) || isGeneratedFile(context.filename, context.sourceCode.text)) return {};
|
|
15429
|
+
return {
|
|
15430
|
+
"Program:exit"(program) {
|
|
15431
|
+
const classes = /* @__PURE__ */ new Map();
|
|
15432
|
+
const abstractBases = /* @__PURE__ */ new Set();
|
|
15433
|
+
for (const statement of program.body) {
|
|
15434
|
+
for (const binding of classBindings(statement)) {
|
|
15435
|
+
classes.set(binding.name, binding.declaration);
|
|
15436
|
+
if (binding.declaration.abstract) abstractBases.add(binding.name);
|
|
15437
|
+
}
|
|
15438
|
+
}
|
|
15439
|
+
const exported = /* @__PURE__ */ new Map();
|
|
15440
|
+
for (const statement of program.body) {
|
|
15441
|
+
if (statement.type === import_utils83.AST_NODE_TYPES.ExportNamedDeclaration) {
|
|
15442
|
+
for (const binding of classBindings(statement)) {
|
|
15443
|
+
exported.set(binding.declaration, binding.name);
|
|
15444
|
+
}
|
|
15445
|
+
if (statement.source !== null || statement.exportKind === "type") continue;
|
|
15446
|
+
for (const specifier of statement.specifiers) {
|
|
15447
|
+
if (specifier.exportKind === "type") continue;
|
|
15448
|
+
const candidate2 = classes.get(specifier.local.name);
|
|
15449
|
+
if (candidate2 === void 0) continue;
|
|
15450
|
+
const exportedName = specifier.exported.type === import_utils83.AST_NODE_TYPES.Identifier ? specifier.exported.name : specifier.exported.value;
|
|
15451
|
+
exported.set(candidate2, exportedName);
|
|
15452
|
+
}
|
|
15453
|
+
continue;
|
|
15454
|
+
}
|
|
15455
|
+
if (statement.type !== import_utils83.AST_NODE_TYPES.ExportDefaultDeclaration) continue;
|
|
15456
|
+
if (statement.declaration.type === import_utils83.AST_NODE_TYPES.ClassDeclaration || statement.declaration.type === import_utils83.AST_NODE_TYPES.ClassExpression) {
|
|
15457
|
+
exported.set(
|
|
15458
|
+
statement.declaration,
|
|
15459
|
+
statement.declaration.id?.name ?? "default"
|
|
15460
|
+
);
|
|
15461
|
+
} else if (statement.declaration.type === import_utils83.AST_NODE_TYPES.Identifier) {
|
|
15462
|
+
const candidate2 = classes.get(statement.declaration.name);
|
|
15463
|
+
if (candidate2 !== void 0) {
|
|
15464
|
+
exported.set(candidate2, statement.declaration.name);
|
|
15465
|
+
}
|
|
15466
|
+
}
|
|
15467
|
+
}
|
|
15468
|
+
for (const [declaration, exportedName] of exported) {
|
|
15469
|
+
const extendsLocalAbstractBase = declaration.superClass?.type === import_utils83.AST_NODE_TYPES.Identifier && abstractBases.has(declaration.superClass.name);
|
|
15470
|
+
if (declaration.abstract || declaration.implements.length > 0 || extendsLocalAbstractBase || !hasPublicInstanceBehavior(declaration)) continue;
|
|
15471
|
+
context.report({
|
|
15472
|
+
node: declaration.id ?? declaration,
|
|
15473
|
+
messageId: "requireContract",
|
|
15474
|
+
data: { name: exportedName }
|
|
15475
|
+
});
|
|
15476
|
+
}
|
|
15477
|
+
}
|
|
15478
|
+
};
|
|
15479
|
+
}
|
|
15480
|
+
});
|
|
15481
|
+
|
|
14913
15482
|
// src/rules/require-port-for-service.ts
|
|
14914
|
-
var
|
|
15483
|
+
var import_utils84 = require("@typescript-eslint/utils");
|
|
14915
15484
|
var REQUIRE_PORT_FOR_SERVICE_DOCUMENTATION = {
|
|
14916
15485
|
summary: "Advise when an exported service with injected collaborators has public methods not covered by its declared ports.",
|
|
14917
15486
|
rationale: "A declared port keeps consumers coupled to the service capability instead of its concrete implementation.",
|
|
@@ -14936,45 +15505,45 @@ var ROUTER_FACTORY_NAME = "Router";
|
|
|
14936
15505
|
var FRAMEWORK_HTTP_TYPES = /* @__PURE__ */ new Set(["Request", "Response", "NextFunction"]);
|
|
14937
15506
|
var STORAGE_ASSIGNMENT_OPERATORS = /* @__PURE__ */ new Set(["=", "&&=", "??=", "||="]);
|
|
14938
15507
|
var staticMemberName6 = (member) => {
|
|
14939
|
-
if (member.property.type ===
|
|
14940
|
-
if (!member.computed && member.property.type ===
|
|
14941
|
-
return member.computed && member.property.type ===
|
|
15508
|
+
if (member.property.type === import_utils84.AST_NODE_TYPES.PrivateIdentifier) return `#${member.property.name}`;
|
|
15509
|
+
if (!member.computed && member.property.type === import_utils84.AST_NODE_TYPES.Identifier) return member.property.name;
|
|
15510
|
+
return member.computed && member.property.type === import_utils84.AST_NODE_TYPES.Literal && typeof member.property.value === "string" ? member.property.value : null;
|
|
14942
15511
|
};
|
|
14943
15512
|
var detachedValueExports = (program) => {
|
|
14944
15513
|
const names = /* @__PURE__ */ new Set();
|
|
14945
15514
|
for (const statement of program.body) {
|
|
14946
|
-
if (statement.type ===
|
|
15515
|
+
if (statement.type === import_utils84.AST_NODE_TYPES.ExportNamedDeclaration && statement.declaration === null && statement.source === null && statement.exportKind !== "type") {
|
|
14947
15516
|
for (const specifier of statement.specifiers) {
|
|
14948
15517
|
if (specifier.exportKind !== "type") names.add(specifier.local.name);
|
|
14949
15518
|
}
|
|
14950
|
-
} else if (statement.type ===
|
|
15519
|
+
} else if (statement.type === import_utils84.AST_NODE_TYPES.ExportDefaultDeclaration && statement.declaration.type === import_utils84.AST_NODE_TYPES.Identifier) {
|
|
14951
15520
|
names.add(statement.declaration.name);
|
|
14952
|
-
} else if (statement.type ===
|
|
15521
|
+
} else if (statement.type === import_utils84.AST_NODE_TYPES.TSExportAssignment && statement.expression.type === import_utils84.AST_NODE_TYPES.Identifier) {
|
|
14953
15522
|
names.add(statement.expression.name);
|
|
14954
15523
|
}
|
|
14955
15524
|
}
|
|
14956
15525
|
return names;
|
|
14957
15526
|
};
|
|
14958
|
-
var isExportedClass2 = (node, detached) => node.parent.type ===
|
|
15527
|
+
var isExportedClass2 = (node, detached) => node.parent.type === import_utils84.AST_NODE_TYPES.ExportNamedDeclaration || node.parent.type === import_utils84.AST_NODE_TYPES.ExportDefaultDeclaration || node.id !== null && detached.has(node.id.name);
|
|
14959
15528
|
var readTypeReference = (annotation) => {
|
|
14960
|
-
if (annotation?.type ===
|
|
15529
|
+
if (annotation?.type === import_utils84.AST_NODE_TYPES.TSUnionType) {
|
|
14961
15530
|
const members = annotation.types.filter(
|
|
14962
|
-
(member) => member.type !==
|
|
15531
|
+
(member) => member.type !== import_utils84.AST_NODE_TYPES.TSUndefinedKeyword && member.type !== import_utils84.AST_NODE_TYPES.TSNullKeyword
|
|
14963
15532
|
);
|
|
14964
15533
|
annotation = members.length === 1 ? members[0] : void 0;
|
|
14965
15534
|
}
|
|
14966
|
-
if (annotation === void 0 || annotation.type !==
|
|
15535
|
+
if (annotation === void 0 || annotation.type !== import_utils84.AST_NODE_TYPES.TSTypeReference) return null;
|
|
14967
15536
|
const { typeName } = annotation;
|
|
14968
|
-
const rightmost = typeName.type ===
|
|
15537
|
+
const rightmost = typeName.type === import_utils84.AST_NODE_TYPES.Identifier ? typeName.name : typeName.type === import_utils84.AST_NODE_TYPES.TSQualifiedName ? typeName.right.name : null;
|
|
14969
15538
|
if (rightmost === null) return null;
|
|
14970
15539
|
return { typeName: rightmost, display: qualifiedName(typeName) };
|
|
14971
15540
|
};
|
|
14972
|
-
var qualifiedName = (name) => name.type ===
|
|
15541
|
+
var qualifiedName = (name) => name.type === import_utils84.AST_NODE_TYPES.Identifier ? name.name : name.type === import_utils84.AST_NODE_TYPES.TSQualifiedName ? `${qualifiedName(name.left)}.${name.right.name}` : "";
|
|
14973
15542
|
var propertySignatureTypes = (members) => {
|
|
14974
15543
|
const types = /* @__PURE__ */ new Map();
|
|
14975
15544
|
for (const member of members) {
|
|
14976
|
-
if (member.type !==
|
|
14977
|
-
if (member.computed || member.key.type !==
|
|
15545
|
+
if (member.type !== import_utils84.AST_NODE_TYPES.TSPropertySignature) continue;
|
|
15546
|
+
if (member.computed || member.key.type !== import_utils84.AST_NODE_TYPES.Identifier) continue;
|
|
14978
15547
|
const reference = readTypeReference(member.typeAnnotation?.typeAnnotation);
|
|
14979
15548
|
if (reference === null) continue;
|
|
14980
15549
|
types.set(member.key.name, reference);
|
|
@@ -14985,18 +15554,18 @@ var fileTypeIndex = (program) => {
|
|
|
14985
15554
|
const objects = /* @__PURE__ */ new Map();
|
|
14986
15555
|
const functionAliases = /* @__PURE__ */ new Set();
|
|
14987
15556
|
for (const statement of program.body) {
|
|
14988
|
-
const declaration = statement.type ===
|
|
14989
|
-
if (declaration?.type ===
|
|
15557
|
+
const declaration = statement.type === import_utils84.AST_NODE_TYPES.ExportNamedDeclaration ? statement.declaration : statement;
|
|
15558
|
+
if (declaration?.type === import_utils84.AST_NODE_TYPES.TSInterfaceDeclaration) {
|
|
14990
15559
|
objects.set(declaration.id.name, propertySignatureTypes(declaration.body.body));
|
|
14991
15560
|
continue;
|
|
14992
15561
|
}
|
|
14993
|
-
if (declaration?.type !==
|
|
15562
|
+
if (declaration?.type !== import_utils84.AST_NODE_TYPES.TSTypeAliasDeclaration) continue;
|
|
14994
15563
|
const aliased = declaration.typeAnnotation;
|
|
14995
|
-
if (aliased.type ===
|
|
15564
|
+
if (aliased.type === import_utils84.AST_NODE_TYPES.TSFunctionType || aliased.type === import_utils84.AST_NODE_TYPES.TSConstructorType) {
|
|
14996
15565
|
functionAliases.add(declaration.id.name);
|
|
14997
15566
|
continue;
|
|
14998
15567
|
}
|
|
14999
|
-
const literals = aliased.type ===
|
|
15568
|
+
const literals = aliased.type === import_utils84.AST_NODE_TYPES.TSTypeLiteral ? [aliased] : aliased.type === import_utils84.AST_NODE_TYPES.TSIntersectionType ? aliased.types.filter((part) => part.type === import_utils84.AST_NODE_TYPES.TSTypeLiteral) : [];
|
|
15000
15569
|
if (literals.length === 0) continue;
|
|
15001
15570
|
const merged = /* @__PURE__ */ new Map();
|
|
15002
15571
|
for (const literal of literals) {
|
|
@@ -15025,10 +15594,10 @@ var readConstructor = (ctor, declared, typeParameters) => {
|
|
|
15025
15594
|
while (pending.length > 0) {
|
|
15026
15595
|
const current = pending.pop();
|
|
15027
15596
|
if (current === void 0) break;
|
|
15028
|
-
if (current.type ===
|
|
15029
|
-
const expression = current.type ===
|
|
15030
|
-
const storedField = expression?.type ===
|
|
15031
|
-
if (expression?.type !==
|
|
15597
|
+
if (current.type === import_utils84.AST_NODE_TYPES.ArrowFunctionExpression || current.type === import_utils84.AST_NODE_TYPES.FunctionExpression || current.type === import_utils84.AST_NODE_TYPES.FunctionDeclaration || current.type === import_utils84.AST_NODE_TYPES.ClassExpression || current.type === import_utils84.AST_NODE_TYPES.ClassDeclaration) continue;
|
|
15598
|
+
const expression = current.type === import_utils84.AST_NODE_TYPES.ExpressionStatement ? current.expression : null;
|
|
15599
|
+
const storedField = expression?.type === import_utils84.AST_NODE_TYPES.AssignmentExpression && expression.left.type === import_utils84.AST_NODE_TYPES.MemberExpression && expression.left.object.type === import_utils84.AST_NODE_TYPES.ThisExpression ? staticMemberName6(expression.left) : null;
|
|
15600
|
+
if (expression?.type !== import_utils84.AST_NODE_TYPES.AssignmentExpression || !STORAGE_ASSIGNMENT_OPERATORS.has(expression.operator) || expression.left.type !== import_utils84.AST_NODE_TYPES.MemberExpression || expression.left.object.type !== import_utils84.AST_NODE_TYPES.ThisExpression || storedField === null) {
|
|
15032
15601
|
for (const key of Object.keys(current)) {
|
|
15033
15602
|
if (key === "parent") continue;
|
|
15034
15603
|
const value = current[key];
|
|
@@ -15041,14 +15610,14 @@ var readConstructor = (ctor, declared, typeParameters) => {
|
|
|
15041
15610
|
continue;
|
|
15042
15611
|
}
|
|
15043
15612
|
let source = expression.right;
|
|
15044
|
-
while (source.type ===
|
|
15045
|
-
if (source.type ===
|
|
15613
|
+
while (source.type === import_utils84.AST_NODE_TYPES.TSNonNullExpression || source.type === import_utils84.AST_NODE_TYPES.TSAsExpression || source.type === import_utils84.AST_NODE_TYPES.TSSatisfiesExpression || source.type === import_utils84.AST_NODE_TYPES.TSTypeAssertion) source = source.expression;
|
|
15614
|
+
if (source.type === import_utils84.AST_NODE_TYPES.NewExpression) {
|
|
15046
15615
|
constructedFields += 1;
|
|
15047
|
-
} else if (source.type ===
|
|
15616
|
+
} else if (source.type === import_utils84.AST_NODE_TYPES.Identifier) {
|
|
15048
15617
|
const fields = storedFieldsFrom.get(source.name) ?? /* @__PURE__ */ new Set();
|
|
15049
15618
|
fields.add(storedField);
|
|
15050
15619
|
storedFieldsFrom.set(source.name, fields);
|
|
15051
|
-
} else if (source.type ===
|
|
15620
|
+
} else if (source.type === import_utils84.AST_NODE_TYPES.MemberExpression && source.object.type === import_utils84.AST_NODE_TYPES.Identifier) {
|
|
15052
15621
|
const fields = storedFieldsFrom.get(source.object.name) ?? /* @__PURE__ */ new Set();
|
|
15053
15622
|
fields.add(storedField);
|
|
15054
15623
|
storedFieldsFrom.set(source.object.name, fields);
|
|
@@ -15066,7 +15635,7 @@ var readConstructor = (ctor, declared, typeParameters) => {
|
|
|
15066
15635
|
const collaborators = [];
|
|
15067
15636
|
for (const parameter of ctor.value.params) {
|
|
15068
15637
|
for (const reference of parameterCollaborators(parameter, declared, storedMemberFieldsFrom)) {
|
|
15069
|
-
const fields = parameter.type ===
|
|
15638
|
+
const fields = parameter.type === import_utils84.AST_NODE_TYPES.TSParameterProperty ? [reference.name] : reference.fields.length > 0 ? reference.fields : [...storedFieldsFrom.get(reference.name) ?? []];
|
|
15070
15639
|
if (fields.length === 0) continue;
|
|
15071
15640
|
if (CONFIGISH_TYPE_RE.test(reference.typeName)) continue;
|
|
15072
15641
|
if (CONFIGISH_NAME_RE.test(reference.name)) continue;
|
|
@@ -15081,8 +15650,8 @@ var readConstructor = (ctor, declared, typeParameters) => {
|
|
|
15081
15650
|
};
|
|
15082
15651
|
var parameterCollaborators = (parameter, declared, storedMemberFieldsFrom) => {
|
|
15083
15652
|
let target = parameter;
|
|
15084
|
-
if (target.type ===
|
|
15085
|
-
if (target.type ===
|
|
15653
|
+
if (target.type === import_utils84.AST_NODE_TYPES.AssignmentPattern) target = target.left;
|
|
15654
|
+
if (target.type === import_utils84.AST_NODE_TYPES.ObjectPattern) {
|
|
15086
15655
|
return objectPatternCollaborators(target, declared);
|
|
15087
15656
|
}
|
|
15088
15657
|
const named2 = namedParameterCollaborator(parameter);
|
|
@@ -15091,9 +15660,9 @@ var parameterCollaborators = (parameter, declared, storedMemberFieldsFrom) => {
|
|
|
15091
15660
|
};
|
|
15092
15661
|
var namedBagCollaborators = (annotated, declared, storedMemberFieldsFrom) => {
|
|
15093
15662
|
let target = annotated;
|
|
15094
|
-
if (target.type ===
|
|
15095
|
-
if (target.type ===
|
|
15096
|
-
if (target.type !==
|
|
15663
|
+
if (target.type === import_utils84.AST_NODE_TYPES.TSParameterProperty) target = target.parameter;
|
|
15664
|
+
if (target.type === import_utils84.AST_NODE_TYPES.AssignmentPattern) target = target.left;
|
|
15665
|
+
if (target.type !== import_utils84.AST_NODE_TYPES.Identifier) return [];
|
|
15097
15666
|
const members = bagMemberTypes(target.typeAnnotation?.typeAnnotation, declared);
|
|
15098
15667
|
if (members === null) return [];
|
|
15099
15668
|
const storedMembers = storedMemberFieldsFrom.get(target.name);
|
|
@@ -15109,9 +15678,9 @@ var namedBagCollaborators = (annotated, declared, storedMemberFieldsFrom) => {
|
|
|
15109
15678
|
};
|
|
15110
15679
|
var namedParameterCollaborator = (annotated) => {
|
|
15111
15680
|
let target = annotated;
|
|
15112
|
-
if (target.type ===
|
|
15113
|
-
if (target.type ===
|
|
15114
|
-
if (target.type !==
|
|
15681
|
+
if (target.type === import_utils84.AST_NODE_TYPES.TSParameterProperty) target = target.parameter;
|
|
15682
|
+
if (target.type === import_utils84.AST_NODE_TYPES.AssignmentPattern) target = target.left;
|
|
15683
|
+
if (target.type !== import_utils84.AST_NODE_TYPES.Identifier) return null;
|
|
15115
15684
|
const reference = readTypeReference(target.typeAnnotation?.typeAnnotation);
|
|
15116
15685
|
if (reference === null) return null;
|
|
15117
15686
|
return { name: target.name, ...reference, fields: [] };
|
|
@@ -15123,11 +15692,11 @@ var objectPatternCollaborators = (pattern, declared) => {
|
|
|
15123
15692
|
if (members === null) return [];
|
|
15124
15693
|
const collaborators = [];
|
|
15125
15694
|
for (const property of pattern.properties) {
|
|
15126
|
-
if (property.type !==
|
|
15127
|
-
if (property.key.type !==
|
|
15695
|
+
if (property.type !== import_utils84.AST_NODE_TYPES.Property || property.computed) continue;
|
|
15696
|
+
if (property.key.type !== import_utils84.AST_NODE_TYPES.Identifier) continue;
|
|
15128
15697
|
const key = property.key.name;
|
|
15129
|
-
const bound = property.value.type ===
|
|
15130
|
-
if (bound.type !==
|
|
15698
|
+
const bound = property.value.type === import_utils84.AST_NODE_TYPES.AssignmentPattern ? property.value.left : property.value;
|
|
15699
|
+
if (bound.type !== import_utils84.AST_NODE_TYPES.Identifier) continue;
|
|
15131
15700
|
if (CONFIGISH_NAME_RE.test(key)) continue;
|
|
15132
15701
|
const reference = members.get(key);
|
|
15133
15702
|
if (reference === void 0) continue;
|
|
@@ -15137,21 +15706,21 @@ var objectPatternCollaborators = (pattern, declared) => {
|
|
|
15137
15706
|
};
|
|
15138
15707
|
var bagMemberTypes = (annotation, declared) => {
|
|
15139
15708
|
if (annotation === void 0) return null;
|
|
15140
|
-
if (annotation.type ===
|
|
15709
|
+
if (annotation.type === import_utils84.AST_NODE_TYPES.TSTypeLiteral) {
|
|
15141
15710
|
return propertySignatureTypes(annotation.members);
|
|
15142
15711
|
}
|
|
15143
|
-
if (annotation.type !==
|
|
15712
|
+
if (annotation.type !== import_utils84.AST_NODE_TYPES.TSTypeReference || annotation.typeName.type !== import_utils84.AST_NODE_TYPES.Identifier) {
|
|
15144
15713
|
return null;
|
|
15145
15714
|
}
|
|
15146
15715
|
return declared().objects.get(annotation.typeName.name) ?? null;
|
|
15147
15716
|
};
|
|
15148
15717
|
var isFrameworkWiring = (body2) => subtreeHas(body2, (node) => {
|
|
15149
|
-
if (node.type ===
|
|
15718
|
+
if (node.type === import_utils84.AST_NODE_TYPES.CallExpression) {
|
|
15150
15719
|
const { callee } = node;
|
|
15151
|
-
if (callee.type ===
|
|
15152
|
-
return callee.type ===
|
|
15720
|
+
if (callee.type === import_utils84.AST_NODE_TYPES.Identifier) return callee.name === ROUTER_FACTORY_NAME;
|
|
15721
|
+
return callee.type === import_utils84.AST_NODE_TYPES.MemberExpression && !callee.computed && callee.property.type === import_utils84.AST_NODE_TYPES.Identifier && callee.property.name === ROUTER_FACTORY_NAME;
|
|
15153
15722
|
}
|
|
15154
|
-
return node.type ===
|
|
15723
|
+
return node.type === import_utils84.AST_NODE_TYPES.TSTypeReference && node.typeName.type === import_utils84.AST_NODE_TYPES.TSQualifiedName && FRAMEWORK_HTTP_TYPES.has(node.typeName.right.name);
|
|
15155
15724
|
});
|
|
15156
15725
|
var subtreeHas = (root, found) => {
|
|
15157
15726
|
let hit = false;
|
|
@@ -15178,19 +15747,19 @@ var invokedInstanceField = (call) => {
|
|
|
15178
15747
|
const direct = instanceField(call.callee);
|
|
15179
15748
|
if (direct !== null) return direct;
|
|
15180
15749
|
let callee = call.callee;
|
|
15181
|
-
while (callee.type ===
|
|
15182
|
-
return callee.type ===
|
|
15750
|
+
while (callee.type === import_utils84.AST_NODE_TYPES.ChainExpression || callee.type === import_utils84.AST_NODE_TYPES.TSAsExpression || callee.type === import_utils84.AST_NODE_TYPES.TSNonNullExpression || callee.type === import_utils84.AST_NODE_TYPES.TSSatisfiesExpression || callee.type === import_utils84.AST_NODE_TYPES.TSTypeAssertion) callee = callee.expression;
|
|
15751
|
+
return callee.type === import_utils84.AST_NODE_TYPES.MemberExpression ? instanceField(callee.object) : null;
|
|
15183
15752
|
};
|
|
15184
15753
|
var instanceField = (candidate2) => {
|
|
15185
15754
|
let node = candidate2;
|
|
15186
|
-
while (node.type ===
|
|
15187
|
-
return node.type ===
|
|
15755
|
+
while (node.type === import_utils84.AST_NODE_TYPES.ChainExpression || node.type === import_utils84.AST_NODE_TYPES.TSAsExpression || node.type === import_utils84.AST_NODE_TYPES.TSNonNullExpression || node.type === import_utils84.AST_NODE_TYPES.TSSatisfiesExpression || node.type === import_utils84.AST_NODE_TYPES.TSTypeAssertion) node = node.expression;
|
|
15756
|
+
return node.type === import_utils84.AST_NODE_TYPES.MemberExpression && node.object.type === import_utils84.AST_NODE_TYPES.ThisExpression ? staticMemberName6(node) : null;
|
|
15188
15757
|
};
|
|
15189
15758
|
var behaviorallyInvokedFields = (body2) => {
|
|
15190
15759
|
const invoked = /* @__PURE__ */ new Set();
|
|
15191
15760
|
const visit = (current) => {
|
|
15192
|
-
if (current.type ===
|
|
15193
|
-
if (current.type ===
|
|
15761
|
+
if (current.type === import_utils84.AST_NODE_TYPES.ClassDeclaration || current.type === import_utils84.AST_NODE_TYPES.ClassExpression || current.type === import_utils84.AST_NODE_TYPES.FunctionDeclaration || current.type === import_utils84.AST_NODE_TYPES.FunctionExpression) return;
|
|
15762
|
+
if (current.type === import_utils84.AST_NODE_TYPES.CallExpression) {
|
|
15194
15763
|
const field = invokedInstanceField(current);
|
|
15195
15764
|
if (field !== null) invoked.add(field);
|
|
15196
15765
|
}
|
|
@@ -15203,14 +15772,14 @@ var behaviorallyInvokedFields = (body2) => {
|
|
|
15203
15772
|
}
|
|
15204
15773
|
};
|
|
15205
15774
|
for (const member of body2.body) {
|
|
15206
|
-
if (member.type ===
|
|
15207
|
-
if (member.type ===
|
|
15775
|
+
if (member.type === import_utils84.AST_NODE_TYPES.StaticBlock || member.static) continue;
|
|
15776
|
+
if (member.type === import_utils84.AST_NODE_TYPES.MethodDefinition) {
|
|
15208
15777
|
if (member.value.body !== null && member.value.body !== void 0) visit(member.value.body);
|
|
15209
15778
|
continue;
|
|
15210
15779
|
}
|
|
15211
|
-
if (member.type !==
|
|
15780
|
+
if (member.type !== import_utils84.AST_NODE_TYPES.PropertyDefinition || member.value === null) continue;
|
|
15212
15781
|
visit(
|
|
15213
|
-
member.value.type ===
|
|
15782
|
+
member.value.type === import_utils84.AST_NODE_TYPES.ArrowFunctionExpression ? member.value.body : member.value
|
|
15214
15783
|
);
|
|
15215
15784
|
}
|
|
15216
15785
|
return invoked;
|
|
@@ -15230,25 +15799,26 @@ var isTransportWrapper = (className, collaborators, program) => {
|
|
|
15230
15799
|
var fileInterfaceNames = (program) => {
|
|
15231
15800
|
const names = [];
|
|
15232
15801
|
for (const statement of program.body) {
|
|
15233
|
-
const declaration = statement.type ===
|
|
15234
|
-
if (declaration?.type ===
|
|
15802
|
+
const declaration = statement.type === import_utils84.AST_NODE_TYPES.ExportNamedDeclaration ? statement.declaration : statement;
|
|
15803
|
+
if (declaration?.type === import_utils84.AST_NODE_TYPES.TSInterfaceDeclaration) names.push(declaration.id.name);
|
|
15235
15804
|
}
|
|
15236
15805
|
return names;
|
|
15237
15806
|
};
|
|
15238
15807
|
var publicMethodNames = (body2, functionAliases) => {
|
|
15239
15808
|
const names = [];
|
|
15240
15809
|
for (const member of body2.body) {
|
|
15241
|
-
if (member.type ===
|
|
15810
|
+
if (member.type === import_utils84.AST_NODE_TYPES.PropertyDefinition) {
|
|
15242
15811
|
if (member.static || member.accessibility === "private" || member.accessibility === "protected") continue;
|
|
15243
|
-
if (member.
|
|
15244
|
-
|
|
15812
|
+
if (member.key.type === import_utils84.AST_NODE_TYPES.PrivateIdentifier) continue;
|
|
15813
|
+
if (member.value?.type !== import_utils84.AST_NODE_TYPES.ArrowFunctionExpression && member.value?.type !== import_utils84.AST_NODE_TYPES.FunctionExpression && member.typeAnnotation?.typeAnnotation.type !== import_utils84.AST_NODE_TYPES.TSFunctionType && !(member.typeAnnotation?.typeAnnotation.type === import_utils84.AST_NODE_TYPES.TSTypeReference && member.typeAnnotation.typeAnnotation.typeName.type === import_utils84.AST_NODE_TYPES.Identifier && functionAliases.has(member.typeAnnotation.typeAnnotation.typeName.name))) continue;
|
|
15814
|
+
names.push(member.key.type === import_utils84.AST_NODE_TYPES.Identifier ? member.key.name : "\u2026");
|
|
15245
15815
|
continue;
|
|
15246
15816
|
}
|
|
15247
|
-
if (member.type !==
|
|
15817
|
+
if (member.type !== import_utils84.AST_NODE_TYPES.MethodDefinition) continue;
|
|
15248
15818
|
if (member.kind !== "method" || member.static) continue;
|
|
15249
15819
|
if (member.accessibility === "private" || member.accessibility === "protected") continue;
|
|
15250
|
-
if (member.key.type ===
|
|
15251
|
-
if (member.key.type ===
|
|
15820
|
+
if (member.key.type === import_utils84.AST_NODE_TYPES.PrivateIdentifier) continue;
|
|
15821
|
+
if (member.key.type === import_utils84.AST_NODE_TYPES.Identifier) names.push(member.key.name);
|
|
15252
15822
|
else names.push("\u2026");
|
|
15253
15823
|
}
|
|
15254
15824
|
return names;
|
|
@@ -15256,13 +15826,13 @@ var publicMethodNames = (body2, functionAliases) => {
|
|
|
15256
15826
|
var isFluentConstructionObject = (node, getText) => {
|
|
15257
15827
|
if (node.id === null) return false;
|
|
15258
15828
|
const methods = node.body.body.filter(
|
|
15259
|
-
(member) => member.type ===
|
|
15829
|
+
(member) => member.type === import_utils84.AST_NODE_TYPES.MethodDefinition && member.kind === "method" && !member.static && member.accessibility !== "private" && member.accessibility !== "protected" && member.value.body !== null
|
|
15260
15830
|
);
|
|
15261
15831
|
if (methods.length === 0) return false;
|
|
15262
15832
|
return methods.every((member) => {
|
|
15263
15833
|
const result = member.value.returnType?.typeAnnotation;
|
|
15264
15834
|
if (result === void 0) return false;
|
|
15265
|
-
const returnsOwnType = result.type ===
|
|
15835
|
+
const returnsOwnType = result.type === import_utils84.AST_NODE_TYPES.TSTypeReference && result.typeName.type === import_utils84.AST_NODE_TYPES.Identifier && result.typeName.name === node.id?.name;
|
|
15266
15836
|
return returnsOwnType || FLUENT_BUILDER_NAME_RE.test(node.id?.name ?? "") && FLUENT_RESULT_TYPE_RE.test(getText(result));
|
|
15267
15837
|
});
|
|
15268
15838
|
};
|
|
@@ -15270,10 +15840,10 @@ function localClassAbstractness(program) {
|
|
|
15270
15840
|
const classes = /* @__PURE__ */ new Map();
|
|
15271
15841
|
const parents = /* @__PURE__ */ new Map();
|
|
15272
15842
|
for (const statement of program.body) {
|
|
15273
|
-
const declaration = statement.type ===
|
|
15274
|
-
if (declaration?.type ===
|
|
15843
|
+
const declaration = statement.type === import_utils84.AST_NODE_TYPES.ExportNamedDeclaration || statement.type === import_utils84.AST_NODE_TYPES.ExportDefaultDeclaration ? statement.declaration : statement;
|
|
15844
|
+
if (declaration?.type === import_utils84.AST_NODE_TYPES.ClassDeclaration && declaration.id !== null) {
|
|
15275
15845
|
classes.set(declaration.id.name, declaration.abstract === true);
|
|
15276
|
-
if (declaration.superClass?.type ===
|
|
15846
|
+
if (declaration.superClass?.type === import_utils84.AST_NODE_TYPES.Identifier) {
|
|
15277
15847
|
parents.set(declaration.id.name, declaration.superClass.name);
|
|
15278
15848
|
}
|
|
15279
15849
|
}
|
|
@@ -15295,43 +15865,43 @@ function localInterfaceSurfaces(program) {
|
|
|
15295
15865
|
const parents = /* @__PURE__ */ new Map();
|
|
15296
15866
|
const functionAliases = /* @__PURE__ */ new Set();
|
|
15297
15867
|
for (const statement of program.body) {
|
|
15298
|
-
const declaration = statement.type ===
|
|
15299
|
-
if (declaration?.type ===
|
|
15868
|
+
const declaration = statement.type === import_utils84.AST_NODE_TYPES.ExportNamedDeclaration ? statement.declaration : statement;
|
|
15869
|
+
if (declaration?.type === import_utils84.AST_NODE_TYPES.TSTypeAliasDeclaration && (declaration.typeAnnotation.type === import_utils84.AST_NODE_TYPES.TSFunctionType || declaration.typeAnnotation.type === import_utils84.AST_NODE_TYPES.TSConstructorType)) functionAliases.add(declaration.id.name);
|
|
15300
15870
|
}
|
|
15301
15871
|
for (const statement of program.body) {
|
|
15302
|
-
const declaration = statement.type ===
|
|
15303
|
-
if (declaration?.type ===
|
|
15872
|
+
const declaration = statement.type === import_utils84.AST_NODE_TYPES.ExportNamedDeclaration ? statement.declaration : statement;
|
|
15873
|
+
if (declaration?.type === import_utils84.AST_NODE_TYPES.TSTypeAliasDeclaration) {
|
|
15304
15874
|
const callables2 = interfaces.get(declaration.id.name) ?? /* @__PURE__ */ new Set();
|
|
15305
|
-
const parts = declaration.typeAnnotation.type ===
|
|
15875
|
+
const parts = declaration.typeAnnotation.type === import_utils84.AST_NODE_TYPES.TSIntersectionType ? declaration.typeAnnotation.types : [declaration.typeAnnotation];
|
|
15306
15876
|
const inherited = parents.get(declaration.id.name) ?? [];
|
|
15307
15877
|
for (const part of parts) {
|
|
15308
|
-
if (part.type ===
|
|
15878
|
+
if (part.type === import_utils84.AST_NODE_TYPES.TSTypeReference && part.typeName.type === import_utils84.AST_NODE_TYPES.Identifier) {
|
|
15309
15879
|
inherited.push(part.typeName.name);
|
|
15310
15880
|
continue;
|
|
15311
15881
|
}
|
|
15312
|
-
if (part.type !==
|
|
15882
|
+
if (part.type !== import_utils84.AST_NODE_TYPES.TSTypeLiteral) continue;
|
|
15313
15883
|
for (const member of part.members) {
|
|
15314
|
-
if (member.type !==
|
|
15315
|
-
if (member.computed || member.key.type !==
|
|
15316
|
-
if (member.type ===
|
|
15884
|
+
if (member.type !== import_utils84.AST_NODE_TYPES.TSMethodSignature && member.type !== import_utils84.AST_NODE_TYPES.TSPropertySignature) continue;
|
|
15885
|
+
if (member.computed || member.key.type !== import_utils84.AST_NODE_TYPES.Identifier) continue;
|
|
15886
|
+
if (member.type === import_utils84.AST_NODE_TYPES.TSMethodSignature) {
|
|
15317
15887
|
callables2.add(member.key.name);
|
|
15318
15888
|
continue;
|
|
15319
15889
|
}
|
|
15320
|
-
if (member.type !==
|
|
15890
|
+
if (member.type !== import_utils84.AST_NODE_TYPES.TSPropertySignature) continue;
|
|
15321
15891
|
const annotation = member.typeAnnotation?.typeAnnotation;
|
|
15322
|
-
if (annotation?.type ===
|
|
15892
|
+
if (annotation?.type === import_utils84.AST_NODE_TYPES.TSFunctionType || annotation?.type === import_utils84.AST_NODE_TYPES.TSTypeReference && annotation.typeName.type === import_utils84.AST_NODE_TYPES.Identifier && functionAliases.has(annotation.typeName.name)) callables2.add(member.key.name);
|
|
15323
15893
|
}
|
|
15324
15894
|
}
|
|
15325
15895
|
interfaces.set(declaration.id.name, callables2);
|
|
15326
15896
|
parents.set(declaration.id.name, inherited);
|
|
15327
15897
|
continue;
|
|
15328
15898
|
}
|
|
15329
|
-
if (declaration?.type !==
|
|
15899
|
+
if (declaration?.type !== import_utils84.AST_NODE_TYPES.TSInterfaceDeclaration) continue;
|
|
15330
15900
|
const callables = interfaces.get(declaration.id.name) ?? /* @__PURE__ */ new Set();
|
|
15331
15901
|
for (const member of declaration.body.body) {
|
|
15332
|
-
if (member.type !==
|
|
15333
|
-
if (member.computed || member.key.type !==
|
|
15334
|
-
if (member.type ===
|
|
15902
|
+
if (member.type !== import_utils84.AST_NODE_TYPES.TSMethodSignature && member.type !== import_utils84.AST_NODE_TYPES.TSPropertySignature) continue;
|
|
15903
|
+
if (member.computed || member.key.type !== import_utils84.AST_NODE_TYPES.Identifier) continue;
|
|
15904
|
+
if (member.type === import_utils84.AST_NODE_TYPES.TSMethodSignature || member.typeAnnotation?.typeAnnotation.type === import_utils84.AST_NODE_TYPES.TSFunctionType || member.typeAnnotation?.typeAnnotation.type === import_utils84.AST_NODE_TYPES.TSTypeReference && member.typeAnnotation.typeAnnotation.typeName.type === import_utils84.AST_NODE_TYPES.Identifier && functionAliases.has(member.typeAnnotation.typeAnnotation.typeName.name)) callables.add(member.key.name);
|
|
15335
15905
|
}
|
|
15336
15906
|
interfaces.set(declaration.id.name, callables);
|
|
15337
15907
|
parents.set(
|
|
@@ -15339,7 +15909,7 @@ function localInterfaceSurfaces(program) {
|
|
|
15339
15909
|
[
|
|
15340
15910
|
...parents.get(declaration.id.name) ?? [],
|
|
15341
15911
|
...declaration.extends.flatMap(
|
|
15342
|
-
(heritage) => heritage.expression.type ===
|
|
15912
|
+
(heritage) => heritage.expression.type === import_utils84.AST_NODE_TYPES.Identifier ? [heritage.expression.name] : ["*"]
|
|
15343
15913
|
)
|
|
15344
15914
|
]
|
|
15345
15915
|
);
|
|
@@ -15366,7 +15936,7 @@ function localInterfaceSurfaces(program) {
|
|
|
15366
15936
|
}
|
|
15367
15937
|
function hasServicePort(node, methods, classes, interfaces) {
|
|
15368
15938
|
if (node.superClass !== null) {
|
|
15369
|
-
if (node.superClass.type !==
|
|
15939
|
+
if (node.superClass.type !== import_utils84.AST_NODE_TYPES.Identifier) return true;
|
|
15370
15940
|
const localAbstract = classes.get(node.superClass.name);
|
|
15371
15941
|
if (localAbstract === void 0 || localAbstract) return true;
|
|
15372
15942
|
}
|
|
@@ -15378,7 +15948,7 @@ function hasServicePort(node, methods, classes, interfaces) {
|
|
|
15378
15948
|
if (node.implements.length === 0) return false;
|
|
15379
15949
|
const combined = /* @__PURE__ */ new Set();
|
|
15380
15950
|
for (const implementation of node.implements) {
|
|
15381
|
-
if (implementation.expression.type !==
|
|
15951
|
+
if (implementation.expression.type !== import_utils84.AST_NODE_TYPES.Identifier) return true;
|
|
15382
15952
|
const name = implementation.expression.name;
|
|
15383
15953
|
const localAbstract = classes.get(name);
|
|
15384
15954
|
if (localAbstract === true) return true;
|
|
@@ -15421,7 +15991,7 @@ var require_port_for_service_default = createRule({
|
|
|
15421
15991
|
if (node.abstract === true) return;
|
|
15422
15992
|
if (node.decorators.length > 0) return;
|
|
15423
15993
|
const ctor = node.body.body.find(
|
|
15424
|
-
(member) => member.type ===
|
|
15994
|
+
(member) => member.type === import_utils84.AST_NODE_TYPES.MethodDefinition && member.kind === "constructor" && member.value.body !== null && member.value.body !== void 0
|
|
15425
15995
|
);
|
|
15426
15996
|
if (ctor === void 0) return;
|
|
15427
15997
|
const constructorFacts = readConstructor(
|
|
@@ -15455,8 +16025,292 @@ var require_port_for_service_default = createRule({
|
|
|
15455
16025
|
}
|
|
15456
16026
|
});
|
|
15457
16027
|
|
|
16028
|
+
// src/rules/require-sql-access-class.ts
|
|
16029
|
+
var import_utils85 = require("@typescript-eslint/utils");
|
|
16030
|
+
var DIRECT_EXECUTION_METHODS = /* @__PURE__ */ new Set([
|
|
16031
|
+
"all",
|
|
16032
|
+
"batch",
|
|
16033
|
+
"dump",
|
|
16034
|
+
"exec",
|
|
16035
|
+
"execute",
|
|
16036
|
+
"get",
|
|
16037
|
+
"pragma",
|
|
16038
|
+
"prepare",
|
|
16039
|
+
"query",
|
|
16040
|
+
"run",
|
|
16041
|
+
"transaction"
|
|
16042
|
+
]);
|
|
16043
|
+
var BUILDER_TERMINAL_METHODS = /* @__PURE__ */ new Set([
|
|
16044
|
+
"execute",
|
|
16045
|
+
"executeQuery",
|
|
16046
|
+
"executeTakeFirst",
|
|
16047
|
+
"executeTakeFirstOrThrow",
|
|
16048
|
+
"stream"
|
|
16049
|
+
]);
|
|
16050
|
+
var BUILDER_METHODS = /* @__PURE__ */ new Set([
|
|
16051
|
+
"delete",
|
|
16052
|
+
"insert",
|
|
16053
|
+
"select",
|
|
16054
|
+
"update"
|
|
16055
|
+
]);
|
|
16056
|
+
var BUILDER_SHORT_TERMINALS = /* @__PURE__ */ new Set([
|
|
16057
|
+
"all",
|
|
16058
|
+
"get",
|
|
16059
|
+
"run"
|
|
16060
|
+
]);
|
|
16061
|
+
var MODEL_EXECUTION_METHODS = /* @__PURE__ */ new Set([
|
|
16062
|
+
"aggregate",
|
|
16063
|
+
"count",
|
|
16064
|
+
"create",
|
|
16065
|
+
"createMany",
|
|
16066
|
+
"createManyAndReturn",
|
|
16067
|
+
"delete",
|
|
16068
|
+
"deleteMany",
|
|
16069
|
+
"findFirst",
|
|
16070
|
+
"findFirstOrThrow",
|
|
16071
|
+
"findMany",
|
|
16072
|
+
"findUnique",
|
|
16073
|
+
"findUniqueOrThrow",
|
|
16074
|
+
"groupBy",
|
|
16075
|
+
"update",
|
|
16076
|
+
"updateMany",
|
|
16077
|
+
"updateManyAndReturn",
|
|
16078
|
+
"upsert"
|
|
16079
|
+
]);
|
|
16080
|
+
var DATABASE_NAMES = /^(?:db|database|connection|pool|prisma|query|transaction|tx)$/iu;
|
|
16081
|
+
var REQUIRE_SQL_ACCESS_CLASS_DOCUMENTATION = {
|
|
16082
|
+
summary: "Keep SQL reads and writes inside a class that receives its database dependency.",
|
|
16083
|
+
rationale: "Free-function database access hides connection ownership and makes transaction, retry, observability, and test boundaries inconsistent.",
|
|
16084
|
+
remediation: "Move the query into a repository or store class and inject the pool, connection, transaction, or typed database binding through its constructor.",
|
|
16085
|
+
category: "architecture",
|
|
16086
|
+
limitations: [
|
|
16087
|
+
"The rule recognizes conventional database receiver names, Cloudflare DB bindings, direct pool.query calls, explicit query-builder terminals, and Prisma-style model delegates; unusually named or heavily aliased clients require architectural review.",
|
|
16088
|
+
"Query construction without a recognized execution terminal is intentionally not reported.",
|
|
16089
|
+
"Constructor injection inherited from a base class or transformed through a wrapper is not inferred by this syntax-only rule."
|
|
16090
|
+
],
|
|
16091
|
+
examples: [
|
|
16092
|
+
{
|
|
16093
|
+
id: "injected-repository",
|
|
16094
|
+
title: "Own queries in an injected repository",
|
|
16095
|
+
outcome: "no-match",
|
|
16096
|
+
files: [
|
|
16097
|
+
{
|
|
16098
|
+
path: "src/user-repository.ts",
|
|
16099
|
+
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); } }"
|
|
16100
|
+
}
|
|
16101
|
+
],
|
|
16102
|
+
focusPath: "src/user-repository.ts",
|
|
16103
|
+
expectedCount: 0,
|
|
16104
|
+
public: true
|
|
16105
|
+
},
|
|
16106
|
+
{
|
|
16107
|
+
id: "free-query",
|
|
16108
|
+
title: "Do not execute SQL in a free function",
|
|
16109
|
+
outcome: "match",
|
|
16110
|
+
files: [
|
|
16111
|
+
{
|
|
16112
|
+
path: "src/users.ts",
|
|
16113
|
+
source: "export function find(database: Database.Database, id: string) { return database.prepare('SELECT id FROM user WHERE id = ?').get(id); }"
|
|
16114
|
+
}
|
|
16115
|
+
],
|
|
16116
|
+
focusPath: "src/users.ts",
|
|
16117
|
+
expectedCount: 1,
|
|
16118
|
+
public: true
|
|
16119
|
+
}
|
|
16120
|
+
]
|
|
16121
|
+
};
|
|
16122
|
+
function memberName5(node) {
|
|
16123
|
+
if (!node.computed && node.property.type === import_utils85.AST_NODE_TYPES.Identifier)
|
|
16124
|
+
return node.property.name;
|
|
16125
|
+
if (node.computed && node.property.type === import_utils85.AST_NODE_TYPES.Literal && typeof node.property.value === "string")
|
|
16126
|
+
return node.property.value;
|
|
16127
|
+
return null;
|
|
16128
|
+
}
|
|
16129
|
+
function isDatabaseOperation(method, receiver) {
|
|
16130
|
+
if (DIRECT_EXECUTION_METHODS.has(method) && databaseReceiver(receiver))
|
|
16131
|
+
return true;
|
|
16132
|
+
if (!expressionHasDatabaseMarker(receiver)) return false;
|
|
16133
|
+
if (BUILDER_TERMINAL_METHODS.has(method) || MODEL_EXECUTION_METHODS.has(method)) return true;
|
|
16134
|
+
return BUILDER_SHORT_TERMINALS.has(method) && expressionCallsBuilder(receiver);
|
|
16135
|
+
}
|
|
16136
|
+
function databaseReceiver(node) {
|
|
16137
|
+
if (node.type === import_utils85.AST_NODE_TYPES.Identifier)
|
|
16138
|
+
return DATABASE_NAMES.test(node.name);
|
|
16139
|
+
if (node.type !== import_utils85.AST_NODE_TYPES.MemberExpression) return false;
|
|
16140
|
+
const name = memberName5(node);
|
|
16141
|
+
return name === "DB" || name !== null && DATABASE_NAMES.test(name);
|
|
16142
|
+
}
|
|
16143
|
+
function databaseRootMember(node) {
|
|
16144
|
+
let current = node;
|
|
16145
|
+
for (; ; ) {
|
|
16146
|
+
if (current.type === import_utils85.AST_NODE_TYPES.ChainExpression) {
|
|
16147
|
+
current = current.expression;
|
|
16148
|
+
continue;
|
|
16149
|
+
}
|
|
16150
|
+
if (current.type === import_utils85.AST_NODE_TYPES.TSAsExpression || current.type === import_utils85.AST_NODE_TYPES.TSNonNullExpression || current.type === import_utils85.AST_NODE_TYPES.TSTypeAssertion) {
|
|
16151
|
+
current = current.expression;
|
|
16152
|
+
continue;
|
|
16153
|
+
}
|
|
16154
|
+
if (current.type === import_utils85.AST_NODE_TYPES.CallExpression) {
|
|
16155
|
+
if (current.callee.type !== import_utils85.AST_NODE_TYPES.MemberExpression) return null;
|
|
16156
|
+
current = current.callee.object;
|
|
16157
|
+
continue;
|
|
16158
|
+
}
|
|
16159
|
+
if (current.type === import_utils85.AST_NODE_TYPES.MemberExpression) {
|
|
16160
|
+
if (current.object.type === import_utils85.AST_NODE_TYPES.ThisExpression)
|
|
16161
|
+
return memberName5(current);
|
|
16162
|
+
current = current.object;
|
|
16163
|
+
continue;
|
|
16164
|
+
}
|
|
16165
|
+
return current.type === import_utils85.AST_NODE_TYPES.Identifier ? current.name : null;
|
|
16166
|
+
}
|
|
16167
|
+
}
|
|
16168
|
+
function expressionHasDatabaseMarker(node) {
|
|
16169
|
+
let current = node;
|
|
16170
|
+
for (; ; ) {
|
|
16171
|
+
if (current.type === import_utils85.AST_NODE_TYPES.ChainExpression) {
|
|
16172
|
+
current = current.expression;
|
|
16173
|
+
continue;
|
|
16174
|
+
}
|
|
16175
|
+
if (current.type === import_utils85.AST_NODE_TYPES.TSAsExpression || current.type === import_utils85.AST_NODE_TYPES.TSNonNullExpression || current.type === import_utils85.AST_NODE_TYPES.TSTypeAssertion) {
|
|
16176
|
+
current = current.expression;
|
|
16177
|
+
continue;
|
|
16178
|
+
}
|
|
16179
|
+
if (current.type === import_utils85.AST_NODE_TYPES.CallExpression) {
|
|
16180
|
+
if (current.callee.type !== import_utils85.AST_NODE_TYPES.MemberExpression) return false;
|
|
16181
|
+
current = current.callee.object;
|
|
16182
|
+
continue;
|
|
16183
|
+
}
|
|
16184
|
+
if (current.type === import_utils85.AST_NODE_TYPES.MemberExpression) {
|
|
16185
|
+
const name = memberName5(current);
|
|
16186
|
+
if (name === "DB" || name !== null && DATABASE_NAMES.test(name))
|
|
16187
|
+
return true;
|
|
16188
|
+
current = current.object;
|
|
16189
|
+
continue;
|
|
16190
|
+
}
|
|
16191
|
+
return current.type === import_utils85.AST_NODE_TYPES.Identifier && DATABASE_NAMES.test(current.name);
|
|
16192
|
+
}
|
|
16193
|
+
}
|
|
16194
|
+
function expressionCallsBuilder(node) {
|
|
16195
|
+
let current = node;
|
|
16196
|
+
for (; ; ) {
|
|
16197
|
+
if (current.type === import_utils85.AST_NODE_TYPES.ChainExpression) {
|
|
16198
|
+
current = current.expression;
|
|
16199
|
+
continue;
|
|
16200
|
+
}
|
|
16201
|
+
if (current.type === import_utils85.AST_NODE_TYPES.TSAsExpression || current.type === import_utils85.AST_NODE_TYPES.TSNonNullExpression || current.type === import_utils85.AST_NODE_TYPES.TSTypeAssertion) {
|
|
16202
|
+
current = current.expression;
|
|
16203
|
+
continue;
|
|
16204
|
+
}
|
|
16205
|
+
if (current.type === import_utils85.AST_NODE_TYPES.CallExpression) {
|
|
16206
|
+
if (current.callee.type !== import_utils85.AST_NODE_TYPES.MemberExpression) return false;
|
|
16207
|
+
const name = memberName5(current.callee);
|
|
16208
|
+
if (name !== null && BUILDER_METHODS.has(name)) return true;
|
|
16209
|
+
current = current.callee.object;
|
|
16210
|
+
continue;
|
|
16211
|
+
}
|
|
16212
|
+
if (current.type !== import_utils85.AST_NODE_TYPES.MemberExpression) return false;
|
|
16213
|
+
current = current.object;
|
|
16214
|
+
}
|
|
16215
|
+
}
|
|
16216
|
+
function owningClass2(node) {
|
|
16217
|
+
let current = node.parent;
|
|
16218
|
+
while (current != null) {
|
|
16219
|
+
if (current.type === import_utils85.AST_NODE_TYPES.ClassDeclaration || current.type === import_utils85.AST_NODE_TYPES.ClassExpression)
|
|
16220
|
+
return current;
|
|
16221
|
+
current = current.parent;
|
|
16222
|
+
}
|
|
16223
|
+
return null;
|
|
16224
|
+
}
|
|
16225
|
+
function injectedMembers(owner) {
|
|
16226
|
+
const injected = /* @__PURE__ */ new Set();
|
|
16227
|
+
const constructor = owner.body.body.find(
|
|
16228
|
+
(member) => member.type === import_utils85.AST_NODE_TYPES.MethodDefinition && member.kind === "constructor"
|
|
16229
|
+
);
|
|
16230
|
+
if (constructor === void 0) return injected;
|
|
16231
|
+
const parameters = /* @__PURE__ */ new Set();
|
|
16232
|
+
for (const parameter of constructor.value.params) {
|
|
16233
|
+
for (const name of parameterNames(parameter)) parameters.add(name);
|
|
16234
|
+
if (parameter.type !== import_utils85.AST_NODE_TYPES.TSParameterProperty) continue;
|
|
16235
|
+
const value = parameter.parameter.type === import_utils85.AST_NODE_TYPES.AssignmentPattern ? parameter.parameter.left : parameter.parameter;
|
|
16236
|
+
if (value.type === import_utils85.AST_NODE_TYPES.Identifier) injected.add(value.name);
|
|
16237
|
+
}
|
|
16238
|
+
const body2 = constructor.value.body;
|
|
16239
|
+
if (body2 === null) return injected;
|
|
16240
|
+
for (const statement of body2.body) {
|
|
16241
|
+
if (statement.type !== import_utils85.AST_NODE_TYPES.ExpressionStatement || statement.expression.type !== import_utils85.AST_NODE_TYPES.AssignmentExpression || statement.expression.operator !== "=") continue;
|
|
16242
|
+
const { left, right } = statement.expression;
|
|
16243
|
+
if (left.type !== import_utils85.AST_NODE_TYPES.MemberExpression) continue;
|
|
16244
|
+
const target = thisRootMember(left);
|
|
16245
|
+
if (target === null) continue;
|
|
16246
|
+
const source = right.type === import_utils85.AST_NODE_TYPES.Identifier ? right.name : right.type === import_utils85.AST_NODE_TYPES.MemberExpression && right.object.type === import_utils85.AST_NODE_TYPES.Identifier ? right.object.name : null;
|
|
16247
|
+
if (source !== null && parameters.has(source)) injected.add(target);
|
|
16248
|
+
}
|
|
16249
|
+
return injected;
|
|
16250
|
+
}
|
|
16251
|
+
function thisRootMember(node) {
|
|
16252
|
+
let current = node;
|
|
16253
|
+
let root = null;
|
|
16254
|
+
while (current.type === import_utils85.AST_NODE_TYPES.MemberExpression) {
|
|
16255
|
+
const name = memberName5(current);
|
|
16256
|
+
if (name === null) return null;
|
|
16257
|
+
root = name;
|
|
16258
|
+
current = current.object;
|
|
16259
|
+
}
|
|
16260
|
+
return current.type === import_utils85.AST_NODE_TYPES.ThisExpression ? root : null;
|
|
16261
|
+
}
|
|
16262
|
+
function parameterNames(parameter) {
|
|
16263
|
+
let value = parameter;
|
|
16264
|
+
if (value.type === import_utils85.AST_NODE_TYPES.TSParameterProperty) value = value.parameter;
|
|
16265
|
+
if (value.type === import_utils85.AST_NODE_TYPES.AssignmentPattern) value = value.left;
|
|
16266
|
+
if (value.type === import_utils85.AST_NODE_TYPES.Identifier) return /* @__PURE__ */ new Set([value.name]);
|
|
16267
|
+
if (value.type !== import_utils85.AST_NODE_TYPES.ObjectPattern) return /* @__PURE__ */ new Set();
|
|
16268
|
+
return new Set(
|
|
16269
|
+
value.properties.flatMap((property) => {
|
|
16270
|
+
if (property.type === import_utils85.AST_NODE_TYPES.RestElement)
|
|
16271
|
+
return property.argument.type === import_utils85.AST_NODE_TYPES.Identifier ? [property.argument.name] : [];
|
|
16272
|
+
const target = property.value.type === import_utils85.AST_NODE_TYPES.AssignmentPattern ? property.value.left : property.value;
|
|
16273
|
+
return target.type === import_utils85.AST_NODE_TYPES.Identifier ? [target.name] : [];
|
|
16274
|
+
})
|
|
16275
|
+
);
|
|
16276
|
+
}
|
|
16277
|
+
var require_sql_access_class_default = createRule({
|
|
16278
|
+
name: "require-sql-access-class",
|
|
16279
|
+
documentation: REQUIRE_SQL_ACCESS_CLASS_DOCUMENTATION,
|
|
16280
|
+
meta: {
|
|
16281
|
+
type: "suggestion",
|
|
16282
|
+
docs: {
|
|
16283
|
+
description: "Keep SQL reads and writes inside a class that receives its database dependency."
|
|
16284
|
+
},
|
|
16285
|
+
schema: [],
|
|
16286
|
+
messages: {
|
|
16287
|
+
moveSqlIntoClass: "Move this database operation into a repository or store class with an injected connection or pool."
|
|
16288
|
+
}
|
|
16289
|
+
},
|
|
16290
|
+
defaultOptions: [],
|
|
16291
|
+
create(context) {
|
|
16292
|
+
if (isTestFile(context.filename) || isGeneratedFile(context.filename, context.sourceCode.text))
|
|
16293
|
+
return {};
|
|
16294
|
+
return {
|
|
16295
|
+
CallExpression(node) {
|
|
16296
|
+
if (node.callee.type !== import_utils85.AST_NODE_TYPES.MemberExpression)
|
|
16297
|
+
return;
|
|
16298
|
+
const method = memberName5(node.callee);
|
|
16299
|
+
if (method === null || !isDatabaseOperation(method, node.callee.object))
|
|
16300
|
+
return;
|
|
16301
|
+
const owner = owningClass2(node);
|
|
16302
|
+
if (owner !== null) {
|
|
16303
|
+
const root = databaseRootMember(node.callee.object);
|
|
16304
|
+
if (root !== null && injectedMembers(owner).has(root)) return;
|
|
16305
|
+
}
|
|
16306
|
+
context.report({ node, messageId: "moveSqlIntoClass" });
|
|
16307
|
+
}
|
|
16308
|
+
};
|
|
16309
|
+
}
|
|
16310
|
+
});
|
|
16311
|
+
|
|
15458
16312
|
// src/rules/require-static-next-matcher.ts
|
|
15459
|
-
var
|
|
16313
|
+
var import_utils86 = require("@typescript-eslint/utils");
|
|
15460
16314
|
var REQUIRE_STATIC_NEXT_MATCHER_DOCUMENTATION = {
|
|
15461
16315
|
summary: "Require Next.js middleware and proxy matcher configuration to contain only build-time literals.",
|
|
15462
16316
|
rationale: "Next.js must statically analyze matcher values at build time; computed values are ignored.",
|
|
@@ -15469,34 +16323,34 @@ var REQUIRE_STATIC_NEXT_MATCHER_DOCUMENTATION = {
|
|
|
15469
16323
|
};
|
|
15470
16324
|
var NEXT_ENTRY_FILE = /(?:^|[/\\])(?:middleware|proxy)\.[cm]?[jt]sx?$/u;
|
|
15471
16325
|
function unwrapExpression3(node) {
|
|
15472
|
-
if (node.type ===
|
|
16326
|
+
if (node.type === import_utils86.AST_NODE_TYPES.TSAsExpression || node.type === import_utils86.AST_NODE_TYPES.TSSatisfiesExpression || node.type === import_utils86.AST_NODE_TYPES.TSNonNullExpression || node.type === import_utils86.AST_NODE_TYPES.TSTypeAssertion) {
|
|
15473
16327
|
return unwrapExpression3(node.expression);
|
|
15474
16328
|
}
|
|
15475
16329
|
return node;
|
|
15476
16330
|
}
|
|
15477
16331
|
function isStaticValue(node) {
|
|
15478
16332
|
const value = unwrapExpression3(node);
|
|
15479
|
-
if (value.type ===
|
|
16333
|
+
if (value.type === import_utils86.AST_NODE_TYPES.Literal) {
|
|
15480
16334
|
return true;
|
|
15481
16335
|
}
|
|
15482
|
-
if (value.type ===
|
|
16336
|
+
if (value.type === import_utils86.AST_NODE_TYPES.TemplateLiteral) {
|
|
15483
16337
|
return value.expressions.length === 0;
|
|
15484
16338
|
}
|
|
15485
|
-
if (value.type ===
|
|
16339
|
+
if (value.type === import_utils86.AST_NODE_TYPES.ArrayExpression) {
|
|
15486
16340
|
return value.elements.every(
|
|
15487
|
-
(element) => element !== null && element.type !==
|
|
16341
|
+
(element) => element !== null && element.type !== import_utils86.AST_NODE_TYPES.SpreadElement && isStaticValue(element)
|
|
15488
16342
|
);
|
|
15489
16343
|
}
|
|
15490
|
-
if (value.type ===
|
|
16344
|
+
if (value.type === import_utils86.AST_NODE_TYPES.ObjectExpression) {
|
|
15491
16345
|
return value.properties.every(
|
|
15492
|
-
(property) => property.type ===
|
|
16346
|
+
(property) => property.type === import_utils86.AST_NODE_TYPES.Property && property.kind === "init" && !property.computed && property.value.type !== import_utils86.AST_NODE_TYPES.AssignmentPattern && isStaticValue(property.value)
|
|
15493
16347
|
);
|
|
15494
16348
|
}
|
|
15495
16349
|
return false;
|
|
15496
16350
|
}
|
|
15497
|
-
function
|
|
16351
|
+
function propertyName6(property) {
|
|
15498
16352
|
if (property.computed) return null;
|
|
15499
|
-
if (property.key.type ===
|
|
16353
|
+
if (property.key.type === import_utils86.AST_NODE_TYPES.Identifier) return property.key.name;
|
|
15500
16354
|
return typeof property.key.value === "string" ? property.key.value : null;
|
|
15501
16355
|
}
|
|
15502
16356
|
var require_static_next_matcher_default = createRule({
|
|
@@ -15519,19 +16373,19 @@ var require_static_next_matcher_default = createRule({
|
|
|
15519
16373
|
}
|
|
15520
16374
|
return {
|
|
15521
16375
|
ExportNamedDeclaration(node) {
|
|
15522
|
-
if (node.declaration?.type !==
|
|
16376
|
+
if (node.declaration?.type !== import_utils86.AST_NODE_TYPES.VariableDeclaration) {
|
|
15523
16377
|
return;
|
|
15524
16378
|
}
|
|
15525
16379
|
for (const declaration of node.declaration.declarations) {
|
|
15526
|
-
if (declaration.id.type !==
|
|
16380
|
+
if (declaration.id.type !== import_utils86.AST_NODE_TYPES.Identifier || declaration.id.name !== "config" || declaration.init === null) {
|
|
15527
16381
|
continue;
|
|
15528
16382
|
}
|
|
15529
16383
|
const config = unwrapExpression3(declaration.init);
|
|
15530
|
-
if (config.type !==
|
|
16384
|
+
if (config.type !== import_utils86.AST_NODE_TYPES.ObjectExpression) {
|
|
15531
16385
|
continue;
|
|
15532
16386
|
}
|
|
15533
16387
|
for (const property of config.properties) {
|
|
15534
|
-
if (property.type !==
|
|
16388
|
+
if (property.type !== import_utils86.AST_NODE_TYPES.Property || propertyName6(property) !== "matcher" || property.value.type === import_utils86.AST_NODE_TYPES.AssignmentPattern) {
|
|
15535
16389
|
continue;
|
|
15536
16390
|
}
|
|
15537
16391
|
if (!isStaticValue(property.value)) {
|
|
@@ -15545,7 +16399,7 @@ var require_static_next_matcher_default = createRule({
|
|
|
15545
16399
|
});
|
|
15546
16400
|
|
|
15547
16401
|
// src/rules/require-use-form-default-values.ts
|
|
15548
|
-
var
|
|
16402
|
+
var import_utils87 = require("@typescript-eslint/utils");
|
|
15549
16403
|
var REQUIRE_USE_FORM_DEFAULT_VALUES_DOCUMENTATION = {
|
|
15550
16404
|
summary: "react-hook-form useForm call without defaultValues",
|
|
15551
16405
|
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.",
|
|
@@ -15599,13 +16453,13 @@ var require_use_form_default_values_default = createRule({
|
|
|
15599
16453
|
if (node.source.value !== "react-hook-form") return;
|
|
15600
16454
|
for (const specifier of node.specifiers) {
|
|
15601
16455
|
if (specifier.type !== "ImportSpecifier" || (specifier.imported.type === "Identifier" ? specifier.imported.name : specifier.imported.value) !== "useForm") continue;
|
|
15602
|
-
const variable =
|
|
16456
|
+
const variable = import_utils87.ASTUtils.findVariable(context.sourceCode.getScope(specifier.local), specifier.local.name);
|
|
15603
16457
|
if (variable) importedHooks.add(variable);
|
|
15604
16458
|
}
|
|
15605
16459
|
},
|
|
15606
16460
|
CallExpression(node) {
|
|
15607
16461
|
if (node.callee.type !== "Identifier") return;
|
|
15608
|
-
const variable =
|
|
16462
|
+
const variable = import_utils87.ASTUtils.findVariable(context.sourceCode.getScope(node.callee), node.callee.name);
|
|
15609
16463
|
const options = node.arguments[0];
|
|
15610
16464
|
if (!variable || !importedHooks.has(variable) || options !== void 0 && options.type !== "ObjectExpression" || hasDefaultValues(options)) return;
|
|
15611
16465
|
context.report({ node, messageId: "requireUseFormDefaultValues" });
|
|
@@ -15615,7 +16469,7 @@ var require_use_form_default_values_default = createRule({
|
|
|
15615
16469
|
});
|
|
15616
16470
|
|
|
15617
16471
|
// src/rules/require-use-server-in-actions-file.ts
|
|
15618
|
-
var
|
|
16472
|
+
var import_utils88 = require("@typescript-eslint/utils");
|
|
15619
16473
|
var ACTION_MODULE_RE = /(?:^|\/)app\/.*\/(?:actions|[^/]+-actions)\.[cm]?[jt]s$/u;
|
|
15620
16474
|
var REQUIRE_USE_SERVER_IN_ACTIONS_FILE_DOCUMENTATION = {
|
|
15621
16475
|
summary: "route action module missing the use server directive",
|
|
@@ -15681,7 +16535,7 @@ var require_use_server_in_actions_file_default = createRule({
|
|
|
15681
16535
|
});
|
|
15682
16536
|
|
|
15683
16537
|
// src/rules/require-zod-form-validation.ts
|
|
15684
|
-
var
|
|
16538
|
+
var import_utils89 = require("@typescript-eslint/utils");
|
|
15685
16539
|
var REQUIRE_ZOD_FORM_VALIDATION_DOCUMENTATION = {
|
|
15686
16540
|
summary: "Require Zod validation (`Schema.parse(...)` / `Schema.safeParse(...)`) when reading values out of a `FormData` object.",
|
|
15687
16541
|
rationale: "FormData values are untrusted strings or files and need runtime validation before use.",
|
|
@@ -15706,14 +16560,14 @@ var FORM_VALUE_METHODS = /* @__PURE__ */ new Set(["get", "getAll"]);
|
|
|
15706
16560
|
var zodReceiverRoot = (node) => {
|
|
15707
16561
|
let current = node;
|
|
15708
16562
|
while (true) {
|
|
15709
|
-
if (current.type ===
|
|
16563
|
+
if (current.type === import_utils89.AST_NODE_TYPES.Identifier) {
|
|
15710
16564
|
return current;
|
|
15711
16565
|
}
|
|
15712
|
-
if (current.type ===
|
|
16566
|
+
if (current.type === import_utils89.AST_NODE_TYPES.CallExpression) {
|
|
15713
16567
|
current = current.callee;
|
|
15714
16568
|
continue;
|
|
15715
16569
|
}
|
|
15716
|
-
if (current.type ===
|
|
16570
|
+
if (current.type === import_utils89.AST_NODE_TYPES.MemberExpression) {
|
|
15717
16571
|
current = current.object;
|
|
15718
16572
|
continue;
|
|
15719
16573
|
}
|
|
@@ -15722,12 +16576,12 @@ var zodReceiverRoot = (node) => {
|
|
|
15722
16576
|
};
|
|
15723
16577
|
var isFormDataMethodCall = (node) => {
|
|
15724
16578
|
let current = node;
|
|
15725
|
-
if (current.type ===
|
|
16579
|
+
if (current.type === import_utils89.AST_NODE_TYPES.AwaitExpression) {
|
|
15726
16580
|
current = current.argument;
|
|
15727
16581
|
}
|
|
15728
|
-
if (current.type !==
|
|
16582
|
+
if (current.type !== import_utils89.AST_NODE_TYPES.CallExpression) return false;
|
|
15729
16583
|
const callee = current.callee;
|
|
15730
|
-
return callee.type ===
|
|
16584
|
+
return callee.type === import_utils89.AST_NODE_TYPES.MemberExpression && !callee.computed && callee.property.type === import_utils89.AST_NODE_TYPES.Identifier && callee.property.name === "formData";
|
|
15731
16585
|
};
|
|
15732
16586
|
var require_zod_form_validation_default = createRule({
|
|
15733
16587
|
name: "require-zod-form-validation",
|
|
@@ -15748,7 +16602,7 @@ var require_zod_form_validation_default = createRule({
|
|
|
15748
16602
|
return {};
|
|
15749
16603
|
}
|
|
15750
16604
|
const zodBindings = /* @__PURE__ */ new Set();
|
|
15751
|
-
const resolvedBinding = (identifier) =>
|
|
16605
|
+
const resolvedBinding = (identifier) => import_utils89.ASTUtils.findVariable(
|
|
15752
16606
|
context.sourceCode.getScope(identifier),
|
|
15753
16607
|
identifier.name
|
|
15754
16608
|
);
|
|
@@ -15758,16 +16612,16 @@ var require_zod_form_validation_default = createRule({
|
|
|
15758
16612
|
return false;
|
|
15759
16613
|
}
|
|
15760
16614
|
const definition = binding.defs[0];
|
|
15761
|
-
if (definition?.type !== "Variable" || definition.node.type !==
|
|
16615
|
+
if (definition?.type !== "Variable" || definition.node.type !== import_utils89.AST_NODE_TYPES.VariableDeclarator) {
|
|
15762
16616
|
return false;
|
|
15763
16617
|
}
|
|
15764
16618
|
const init = definition.node.init;
|
|
15765
|
-
return init?.type ===
|
|
16619
|
+
return init?.type === import_utils89.AST_NODE_TYPES.ObjectExpression || init?.type === import_utils89.AST_NODE_TYPES.ArrayExpression || init?.type === import_utils89.AST_NODE_TYPES.Literal || init?.type === import_utils89.AST_NODE_TYPES.ArrowFunctionExpression || init?.type === import_utils89.AST_NODE_TYPES.FunctionExpression;
|
|
15766
16620
|
};
|
|
15767
16621
|
const isZodParseCall = (node) => {
|
|
15768
|
-
if (node.type !==
|
|
16622
|
+
if (node.type !== import_utils89.AST_NODE_TYPES.CallExpression) return false;
|
|
15769
16623
|
const callee = node.callee;
|
|
15770
|
-
if (callee.type !==
|
|
16624
|
+
if (callee.type !== import_utils89.AST_NODE_TYPES.MemberExpression || callee.computed || callee.property.type !== import_utils89.AST_NODE_TYPES.Identifier || !ZOD_PARSE_METHODS.has(callee.property.name)) {
|
|
15771
16625
|
return false;
|
|
15772
16626
|
}
|
|
15773
16627
|
const root = zodReceiverRoot(callee.object);
|
|
@@ -15776,14 +16630,14 @@ var require_zod_form_validation_default = createRule({
|
|
|
15776
16630
|
return binding !== null && zodBindings.has(binding) || (root.name === "z" || ZOD_SCHEMA_NAME_RE.test(root.name)) && !isProvablyNonZodLocal(root);
|
|
15777
16631
|
};
|
|
15778
16632
|
const isFormSourceIdentifier = (node) => {
|
|
15779
|
-
if (node.type !==
|
|
16633
|
+
if (node.type !== import_utils89.AST_NODE_TYPES.Identifier) return false;
|
|
15780
16634
|
const conventionalName = /formdata/i.test(node.name);
|
|
15781
16635
|
let scope = context.sourceCode.getScope(node);
|
|
15782
16636
|
while (scope !== null) {
|
|
15783
16637
|
const variable = scope.set.get(node.name);
|
|
15784
16638
|
if (variable !== void 0 && variable.defs.length === 1) {
|
|
15785
16639
|
const def = variable.defs[0];
|
|
15786
|
-
if (def !== void 0 && def.type === "Variable" && def.node.type ===
|
|
16640
|
+
if (def !== void 0 && def.type === "Variable" && def.node.type === import_utils89.AST_NODE_TYPES.VariableDeclarator && def.node.init !== null) {
|
|
15787
16641
|
return isFormDataMethodCall(def.node.init);
|
|
15788
16642
|
}
|
|
15789
16643
|
return def?.type === "Parameter" && conventionalName;
|
|
@@ -15794,8 +16648,8 @@ var require_zod_form_validation_default = createRule({
|
|
|
15794
16648
|
};
|
|
15795
16649
|
const isFormDataGetCall = (node) => {
|
|
15796
16650
|
const callee = node.callee;
|
|
15797
|
-
if (callee.type !==
|
|
15798
|
-
if (callee.property.type !==
|
|
16651
|
+
if (callee.type !== import_utils89.AST_NODE_TYPES.MemberExpression) return false;
|
|
16652
|
+
if (callee.property.type !== import_utils89.AST_NODE_TYPES.Identifier || !FORM_VALUE_METHODS.has(callee.property.name)) {
|
|
15799
16653
|
return false;
|
|
15800
16654
|
}
|
|
15801
16655
|
return isFormSourceIdentifier(callee.object);
|
|
@@ -15811,16 +16665,16 @@ var require_zod_form_validation_default = createRule({
|
|
|
15811
16665
|
const hasZodParseAncestor = (node) => zodParseAncestor(node) !== null;
|
|
15812
16666
|
const isInstanceofNarrowing = (node) => {
|
|
15813
16667
|
const parent = node.parent;
|
|
15814
|
-
return parent !== null && parent !== void 0 && parent.type ===
|
|
16668
|
+
return parent !== null && parent !== void 0 && parent.type === import_utils89.AST_NODE_TYPES.BinaryExpression && parent.operator === "instanceof" && parent.left === node && parent.right.type === import_utils89.AST_NODE_TYPES.Identifier && (parent.right.name === "File" || parent.right.name === "Blob");
|
|
15815
16669
|
};
|
|
15816
16670
|
const boundDeclarator = (node) => {
|
|
15817
16671
|
let current = node;
|
|
15818
16672
|
let parent = current.parent;
|
|
15819
|
-
while ((parent.type ===
|
|
16673
|
+
while ((parent.type === import_utils89.AST_NODE_TYPES.TSAsExpression || parent.type === import_utils89.AST_NODE_TYPES.TSSatisfiesExpression || parent.type === import_utils89.AST_NODE_TYPES.TSNonNullExpression || parent.type === import_utils89.AST_NODE_TYPES.ChainExpression) && parent.expression === current) {
|
|
15820
16674
|
current = parent;
|
|
15821
16675
|
parent = current.parent;
|
|
15822
16676
|
}
|
|
15823
|
-
if (parent.type ===
|
|
16677
|
+
if (parent.type === import_utils89.AST_NODE_TYPES.VariableDeclarator && parent.init === current && parent.id.type === import_utils89.AST_NODE_TYPES.Identifier) {
|
|
15824
16678
|
return parent;
|
|
15825
16679
|
}
|
|
15826
16680
|
return null;
|
|
@@ -15829,7 +16683,7 @@ var require_zod_form_validation_default = createRule({
|
|
|
15829
16683
|
let current = node;
|
|
15830
16684
|
while (current.parent !== void 0) {
|
|
15831
16685
|
const parent = current.parent;
|
|
15832
|
-
if (parent.type ===
|
|
16686
|
+
if (parent.type === import_utils89.AST_NODE_TYPES.BlockStatement || parent.type === import_utils89.AST_NODE_TYPES.Program) {
|
|
15833
16687
|
return current;
|
|
15834
16688
|
}
|
|
15835
16689
|
current = parent;
|
|
@@ -15838,12 +16692,12 @@ var require_zod_form_validation_default = createRule({
|
|
|
15838
16692
|
};
|
|
15839
16693
|
const zodParseMethod = (call) => {
|
|
15840
16694
|
const callee = call.callee;
|
|
15841
|
-
return callee.type ===
|
|
16695
|
+
return callee.type === import_utils89.AST_NODE_TYPES.MemberExpression && !callee.computed && callee.property.type === import_utils89.AST_NODE_TYPES.Identifier ? callee.property.name : null;
|
|
15842
16696
|
};
|
|
15843
16697
|
const hasConditionalAncestorBeforeStatement = (node, statement) => {
|
|
15844
16698
|
let current = node.parent;
|
|
15845
16699
|
while (current !== void 0 && current !== statement) {
|
|
15846
|
-
if (current.type ===
|
|
16700
|
+
if (current.type === import_utils89.AST_NODE_TYPES.LogicalExpression || current.type === import_utils89.AST_NODE_TYPES.ConditionalExpression) {
|
|
15847
16701
|
return true;
|
|
15848
16702
|
}
|
|
15849
16703
|
current = current.parent;
|
|
@@ -15853,7 +16707,7 @@ var require_zod_form_validation_default = createRule({
|
|
|
15853
16707
|
const isAwaitedBeforeStatement = (node, statement) => {
|
|
15854
16708
|
let current = node.parent;
|
|
15855
16709
|
while (current !== void 0 && current !== statement) {
|
|
15856
|
-
if (current.type ===
|
|
16710
|
+
if (current.type === import_utils89.AST_NODE_TYPES.AwaitExpression) return true;
|
|
15857
16711
|
current = current.parent;
|
|
15858
16712
|
}
|
|
15859
16713
|
return false;
|
|
@@ -15866,7 +16720,7 @@ var require_zod_form_validation_default = createRule({
|
|
|
15866
16720
|
if (declarationStatement === null || validationStatement === null || declarationStatement.parent !== validationStatement.parent || validationStatement.range[0] <= declarationStatement.range[1] || hasConditionalAncestorBeforeStatement(parse2, validationStatement)) {
|
|
15867
16721
|
return null;
|
|
15868
16722
|
}
|
|
15869
|
-
if (validationStatement.type !==
|
|
16723
|
+
if (validationStatement.type !== import_utils89.AST_NODE_TYPES.VariableDeclaration && validationStatement.type !== import_utils89.AST_NODE_TYPES.ExpressionStatement) {
|
|
15870
16724
|
return null;
|
|
15871
16725
|
}
|
|
15872
16726
|
const method = zodParseMethod(parse2);
|
|
@@ -15878,16 +16732,16 @@ var require_zod_form_validation_default = createRule({
|
|
|
15878
16732
|
};
|
|
15879
16733
|
const isSafePrevalidationInspection = (identifier) => {
|
|
15880
16734
|
const parent = identifier.parent;
|
|
15881
|
-
if (parent.type ===
|
|
16735
|
+
if (parent.type === import_utils89.AST_NODE_TYPES.UnaryExpression && parent.operator === "typeof") {
|
|
15882
16736
|
return true;
|
|
15883
16737
|
}
|
|
15884
|
-
if (parent.type !==
|
|
16738
|
+
if (parent.type !== import_utils89.AST_NODE_TYPES.BinaryExpression || parent.left !== identifier) {
|
|
15885
16739
|
return false;
|
|
15886
16740
|
}
|
|
15887
16741
|
if (parent.operator === "instanceof") {
|
|
15888
|
-
return parent.right.type ===
|
|
16742
|
+
return parent.right.type === import_utils89.AST_NODE_TYPES.Identifier && (parent.right.name === "File" || parent.right.name === "Blob");
|
|
15889
16743
|
}
|
|
15890
|
-
return ["===", "!==", "==", "!="].includes(parent.operator) && (parent.right.type ===
|
|
16744
|
+
return ["===", "!==", "==", "!="].includes(parent.operator) && (parent.right.type === import_utils89.AST_NODE_TYPES.Literal && parent.right.value === null || parent.right.type === import_utils89.AST_NODE_TYPES.Identifier && parent.right.name === "undefined");
|
|
15891
16745
|
};
|
|
15892
16746
|
const isDescendantOf = (node, ancestor) => {
|
|
15893
16747
|
let current = node;
|
|
@@ -15898,23 +16752,23 @@ var require_zod_form_validation_default = createRule({
|
|
|
15898
16752
|
return false;
|
|
15899
16753
|
};
|
|
15900
16754
|
const blockTerminates = (node) => {
|
|
15901
|
-
if (node.type ===
|
|
16755
|
+
if (node.type === import_utils89.AST_NODE_TYPES.ReturnStatement || node.type === import_utils89.AST_NODE_TYPES.ThrowStatement) {
|
|
15902
16756
|
return true;
|
|
15903
16757
|
}
|
|
15904
|
-
if (node.type !==
|
|
16758
|
+
if (node.type !== import_utils89.AST_NODE_TYPES.BlockStatement || node.body.length === 0) return false;
|
|
15905
16759
|
const last = node.body.at(-1);
|
|
15906
16760
|
return last !== void 0 && blockTerminates(last);
|
|
15907
16761
|
};
|
|
15908
16762
|
const narrowingIf = (identifier) => {
|
|
15909
16763
|
const comparison = identifier.parent;
|
|
15910
|
-
if (comparison?.type !==
|
|
16764
|
+
if (comparison?.type !== import_utils89.AST_NODE_TYPES.BinaryExpression || comparison.operator !== "instanceof" || comparison.left !== identifier || comparison.right.type !== import_utils89.AST_NODE_TYPES.Identifier || comparison.right.name !== "File" && comparison.right.name !== "Blob") {
|
|
15911
16765
|
return null;
|
|
15912
16766
|
}
|
|
15913
16767
|
const maybeNegation = comparison.parent;
|
|
15914
|
-
const negated = maybeNegation?.type ===
|
|
16768
|
+
const negated = maybeNegation?.type === import_utils89.AST_NODE_TYPES.UnaryExpression && maybeNegation.operator === "!";
|
|
15915
16769
|
const test = negated ? maybeNegation : comparison;
|
|
15916
16770
|
const branch = test.parent;
|
|
15917
|
-
return branch?.type ===
|
|
16771
|
+
return branch?.type === import_utils89.AST_NODE_TYPES.IfStatement && branch.test === test ? { branch, positive: !negated } : null;
|
|
15918
16772
|
};
|
|
15919
16773
|
const useDominatedByNarrowing = (use, narrowings) => narrowings.some(({ branch, positive }) => {
|
|
15920
16774
|
if (positive) return isDescendantOf(use, branch.consequent);
|
|
@@ -15934,7 +16788,7 @@ var require_zod_form_validation_default = createRule({
|
|
|
15934
16788
|
const variable = context.sourceCode.getDeclaredVariables(declarator)[0];
|
|
15935
16789
|
if (variable === void 0) return false;
|
|
15936
16790
|
const references = variable.references.filter((reference) => !reference.isWriteOnly()).map((reference) => reference.identifier).filter(
|
|
15937
|
-
(identifier) => identifier.type ===
|
|
16791
|
+
(identifier) => identifier.type === import_utils89.AST_NODE_TYPES.Identifier
|
|
15938
16792
|
);
|
|
15939
16793
|
if (references.length === 0) return false;
|
|
15940
16794
|
const narrowings = references.map(narrowingIf).filter(
|
|
@@ -15960,7 +16814,7 @@ var require_zod_form_validation_default = createRule({
|
|
|
15960
16814
|
ImportDeclaration(node) {
|
|
15961
16815
|
if (!isZodModule(node.source.value)) return;
|
|
15962
16816
|
for (const specifier of node.specifiers) {
|
|
15963
|
-
if (specifier.type ===
|
|
16817
|
+
if (specifier.type === import_utils89.AST_NODE_TYPES.ImportNamespaceSpecifier || specifier.type === import_utils89.AST_NODE_TYPES.ImportDefaultSpecifier || specifier.type === import_utils89.AST_NODE_TYPES.ImportSpecifier && (specifier.imported.type === import_utils89.AST_NODE_TYPES.Identifier ? specifier.imported.name === "z" : specifier.imported.value === "z")) {
|
|
15964
16818
|
const binding = resolvedBinding(specifier.local);
|
|
15965
16819
|
if (binding !== null) zodBindings.add(binding);
|
|
15966
16820
|
}
|
|
@@ -15981,7 +16835,7 @@ var require_zod_form_validation_default = createRule({
|
|
|
15981
16835
|
});
|
|
15982
16836
|
|
|
15983
16837
|
// src/rules/store-insert-requires-on-conflict.ts
|
|
15984
|
-
var
|
|
16838
|
+
var import_utils90 = require("@typescript-eslint/utils");
|
|
15985
16839
|
var STORE_INSERT_REQUIRES_ON_CONFLICT_DOCUMENTATION = {
|
|
15986
16840
|
summary: "Require embedded inserts in explicitly replayable callables to carry conflict handling.",
|
|
15987
16841
|
rationale: "A callable named as an enqueue, seed, migration, schedule, ensure, or upsert promises replay safety.",
|
|
@@ -16045,7 +16899,7 @@ var store_insert_requires_on_conflict_default = createRule({
|
|
|
16045
16899
|
});
|
|
16046
16900
|
|
|
16047
16901
|
// src/rules/stepdown.ts
|
|
16048
|
-
var
|
|
16902
|
+
var import_utils91 = require("@typescript-eslint/utils");
|
|
16049
16903
|
var STEPDOWN_DOCUMENTATION = {
|
|
16050
16904
|
summary: "Place a private helper below its sole direct same-scope caller.",
|
|
16051
16905
|
rationale: "Caller-first ordering lets a reader follow the main flow before descending into implementation details.",
|
|
@@ -16065,7 +16919,7 @@ var STEPDOWN_DOCUMENTATION = {
|
|
|
16065
16919
|
]
|
|
16066
16920
|
};
|
|
16067
16921
|
function isFunction(node) {
|
|
16068
|
-
return node.type ===
|
|
16922
|
+
return node.type === import_utils91.AST_NODE_TYPES.ArrowFunctionExpression || node.type === import_utils91.AST_NODE_TYPES.FunctionDeclaration || node.type === import_utils91.AST_NODE_TYPES.FunctionExpression;
|
|
16069
16923
|
}
|
|
16070
16924
|
function reportMisordered(context, candidates, scopeDefinitions, calls, pinned, canMove = () => true, makeFix) {
|
|
16071
16925
|
const byName = new Map(scopeDefinitions.map((definition) => [definition.name, definition]));
|
|
@@ -16162,8 +17016,8 @@ function moduleScope(context, program) {
|
|
|
16162
17016
|
for (const node of declarations) counts.set(node.name, (counts.get(node.name) ?? 0) + 1);
|
|
16163
17017
|
const overloadNames = new Set(
|
|
16164
17018
|
program.body.flatMap((statement) => {
|
|
16165
|
-
const node = statement.type ===
|
|
16166
|
-
return node?.type ===
|
|
17019
|
+
const node = statement.type === import_utils91.AST_NODE_TYPES.ExportNamedDeclaration ? statement.declaration : statement;
|
|
17020
|
+
return node?.type === import_utils91.AST_NODE_TYPES.TSDeclareFunction && node.id !== null ? [node.id.name] : [];
|
|
16167
17021
|
})
|
|
16168
17022
|
);
|
|
16169
17023
|
const exported = exportedNames(program);
|
|
@@ -16187,7 +17041,7 @@ function moduleScope(context, program) {
|
|
|
16187
17041
|
const nearestFunction2 = [...ancestors].reverse().find(isFunction);
|
|
16188
17042
|
const parent = identifier.parent;
|
|
16189
17043
|
const callerDefinition = nearestFunction2 === void 0 ? void 0 : byFunction.get(nearestFunction2);
|
|
16190
|
-
if (callerDefinition === void 0 || parent.type !==
|
|
17044
|
+
if (callerDefinition === void 0 || parent.type !== import_utils91.AST_NODE_TYPES.CallExpression || parent.callee !== identifier) {
|
|
16191
17045
|
pinned.add(definition.name);
|
|
16192
17046
|
continue;
|
|
16193
17047
|
}
|
|
@@ -16202,38 +17056,38 @@ function moduleScope(context, program) {
|
|
|
16202
17056
|
function exportedNames(program) {
|
|
16203
17057
|
const names = /* @__PURE__ */ new Set();
|
|
16204
17058
|
for (const statement of program.body) {
|
|
16205
|
-
if (statement.type !==
|
|
16206
|
-
if (statement.declaration?.type ===
|
|
17059
|
+
if (statement.type !== import_utils91.AST_NODE_TYPES.ExportNamedDeclaration || statement.exportKind === "type" || statement.source !== null) continue;
|
|
17060
|
+
if (statement.declaration?.type === import_utils91.AST_NODE_TYPES.FunctionDeclaration && statement.declaration.id !== null) {
|
|
16207
17061
|
names.add(statement.declaration.id.name);
|
|
16208
17062
|
}
|
|
16209
|
-
if (statement.declaration?.type ===
|
|
17063
|
+
if (statement.declaration?.type === import_utils91.AST_NODE_TYPES.VariableDeclaration) {
|
|
16210
17064
|
for (const declarator of statement.declaration.declarations) {
|
|
16211
|
-
if (declarator.id.type ===
|
|
17065
|
+
if (declarator.id.type === import_utils91.AST_NODE_TYPES.Identifier) names.add(declarator.id.name);
|
|
16212
17066
|
}
|
|
16213
17067
|
}
|
|
16214
17068
|
for (const specifier of statement.specifiers) {
|
|
16215
|
-
if (specifier.exportKind !== "type" && specifier.local.type ===
|
|
17069
|
+
if (specifier.exportKind !== "type" && specifier.local.type === import_utils91.AST_NODE_TYPES.Identifier) {
|
|
16216
17070
|
names.add(specifier.local.name);
|
|
16217
17071
|
}
|
|
16218
17072
|
}
|
|
16219
17073
|
}
|
|
16220
17074
|
for (const statement of program.body) {
|
|
16221
|
-
if (statement.type ===
|
|
16222
|
-
if (statement.type ===
|
|
17075
|
+
if (statement.type === import_utils91.AST_NODE_TYPES.ExportDefaultDeclaration && statement.declaration.type === import_utils91.AST_NODE_TYPES.Identifier) names.add(statement.declaration.name);
|
|
17076
|
+
if (statement.type === import_utils91.AST_NODE_TYPES.ExportDefaultDeclaration && statement.declaration.type === import_utils91.AST_NODE_TYPES.FunctionDeclaration && statement.declaration.id !== null) names.add(statement.declaration.id.name);
|
|
16223
17077
|
}
|
|
16224
17078
|
return names;
|
|
16225
17079
|
}
|
|
16226
17080
|
function moduleDefinitions(program) {
|
|
16227
17081
|
const definitions = [];
|
|
16228
17082
|
for (const statement of program.body) {
|
|
16229
|
-
const node = statement.type ===
|
|
16230
|
-
if (node?.type ===
|
|
17083
|
+
const node = statement.type === import_utils91.AST_NODE_TYPES.ExportNamedDeclaration || statement.type === import_utils91.AST_NODE_TYPES.ExportDefaultDeclaration ? statement.declaration : statement;
|
|
17084
|
+
if (node?.type === import_utils91.AST_NODE_TYPES.FunctionDeclaration && node.id !== null && node.body !== null) {
|
|
16231
17085
|
definitions.push({ name: node.id.name, node, functionNode: node, bindingNode: node });
|
|
16232
17086
|
continue;
|
|
16233
17087
|
}
|
|
16234
|
-
if (node?.type !==
|
|
17088
|
+
if (node?.type !== import_utils91.AST_NODE_TYPES.VariableDeclaration || node.kind !== "const") continue;
|
|
16235
17089
|
for (const declarator of node.declarations) {
|
|
16236
|
-
if (declarator.id.type ===
|
|
17090
|
+
if (declarator.id.type === import_utils91.AST_NODE_TYPES.Identifier && declarator.init !== null && isFunction(declarator.init)) {
|
|
16237
17091
|
definitions.push({
|
|
16238
17092
|
name: declarator.id.name,
|
|
16239
17093
|
node: declarator,
|
|
@@ -16246,21 +17100,21 @@ function moduleDefinitions(program) {
|
|
|
16246
17100
|
return definitions;
|
|
16247
17101
|
}
|
|
16248
17102
|
function methodName(node) {
|
|
16249
|
-
if (node.key.type ===
|
|
16250
|
-
return !node.computed && node.key.type ===
|
|
17103
|
+
if (node.key.type === import_utils91.AST_NODE_TYPES.PrivateIdentifier) return `#${node.key.name}`;
|
|
17104
|
+
return !node.computed && node.key.type === import_utils91.AST_NODE_TYPES.Identifier ? node.key.name : null;
|
|
16251
17105
|
}
|
|
16252
17106
|
function referencedMethod(context, node, classVariables) {
|
|
16253
|
-
const objectVariable = node.object.type ===
|
|
17107
|
+
const objectVariable = node.object.type === import_utils91.AST_NODE_TYPES.Identifier ? import_utils91.ASTUtils.findVariable(context.sourceCode.getScope(node.object), node.object.name) : null;
|
|
16254
17108
|
const isClassReference = objectVariable !== null && classVariables.has(objectVariable);
|
|
16255
|
-
if (node.object.type !==
|
|
16256
|
-
if (node.property.type ===
|
|
16257
|
-
if (!node.computed && node.property.type ===
|
|
16258
|
-
return node.computed && node.property.type ===
|
|
17109
|
+
if (node.object.type !== import_utils91.AST_NODE_TYPES.ThisExpression && !isClassReference) return null;
|
|
17110
|
+
if (node.property.type === import_utils91.AST_NODE_TYPES.PrivateIdentifier) return `#${node.property.name}`;
|
|
17111
|
+
if (!node.computed && node.property.type === import_utils91.AST_NODE_TYPES.Identifier) return node.property.name;
|
|
17112
|
+
return node.computed && node.property.type === import_utils91.AST_NODE_TYPES.Literal && typeof node.property.value === "string" ? node.property.value : null;
|
|
16259
17113
|
}
|
|
16260
17114
|
function referencedPropertyName(node) {
|
|
16261
|
-
if (node.property.type ===
|
|
16262
|
-
if (!node.computed && node.property.type ===
|
|
16263
|
-
return node.computed && node.property.type ===
|
|
17115
|
+
if (node.property.type === import_utils91.AST_NODE_TYPES.PrivateIdentifier) return `#${node.property.name}`;
|
|
17116
|
+
if (!node.computed && node.property.type === import_utils91.AST_NODE_TYPES.Identifier) return node.property.name;
|
|
17117
|
+
return node.computed && node.property.type === import_utils91.AST_NODE_TYPES.Literal && typeof node.property.value === "string" ? node.property.value : null;
|
|
16264
17118
|
}
|
|
16265
17119
|
function walk2(node, visitorKeys, visit, nestedFunction = false) {
|
|
16266
17120
|
visit(node, nestedFunction);
|
|
@@ -16276,7 +17130,7 @@ function walk2(node, visitorKeys, visit, nestedFunction = false) {
|
|
|
16276
17130
|
}
|
|
16277
17131
|
function classScope(context, node, computedReferenceNames) {
|
|
16278
17132
|
const methods = node.body.body.filter(
|
|
16279
|
-
(member) => member.type ===
|
|
17133
|
+
(member) => member.type === import_utils91.AST_NODE_TYPES.MethodDefinition
|
|
16280
17134
|
);
|
|
16281
17135
|
const counts = /* @__PURE__ */ new Map();
|
|
16282
17136
|
for (const method of methods) {
|
|
@@ -16284,8 +17138,8 @@ function classScope(context, node, computedReferenceNames) {
|
|
|
16284
17138
|
if (name !== null) counts.set(name, (counts.get(name) ?? 0) + 1);
|
|
16285
17139
|
}
|
|
16286
17140
|
for (const member of node.body.body) {
|
|
16287
|
-
if (member.type !==
|
|
16288
|
-
const name = !member.computed && member.key.type ===
|
|
17141
|
+
if (member.type !== import_utils91.AST_NODE_TYPES.TSAbstractMethodDefinition) continue;
|
|
17142
|
+
const name = !member.computed && member.key.type === import_utils91.AST_NODE_TYPES.Identifier ? member.key.name : null;
|
|
16289
17143
|
if (name !== null) counts.set(name, (counts.get(name) ?? 0) + 1);
|
|
16290
17144
|
}
|
|
16291
17145
|
const scopeDefinitions = methods.flatMap((method) => {
|
|
@@ -16294,7 +17148,7 @@ function classScope(context, node, computedReferenceNames) {
|
|
|
16294
17148
|
});
|
|
16295
17149
|
const definitions = methods.flatMap((method) => {
|
|
16296
17150
|
const name = methodName(method);
|
|
16297
|
-
const isPrivate = method.accessibility === "private" || method.key.type ===
|
|
17151
|
+
const isPrivate = method.accessibility === "private" || method.key.type === import_utils91.AST_NODE_TYPES.PrivateIdentifier;
|
|
16298
17152
|
return name !== null && isPrivate && counts.get(name) === 1 && method.decorators.length === 0 ? [{ name, node: method }] : [];
|
|
16299
17153
|
});
|
|
16300
17154
|
if (definitions.length === 0) return;
|
|
@@ -16303,11 +17157,11 @@ function classScope(context, node, computedReferenceNames) {
|
|
|
16303
17157
|
const pinned = /* @__PURE__ */ new Set();
|
|
16304
17158
|
const classVariables = /* @__PURE__ */ new Set();
|
|
16305
17159
|
if (node.id !== null) {
|
|
16306
|
-
const internal =
|
|
17160
|
+
const internal = import_utils91.ASTUtils.findVariable(context.sourceCode.getScope(node), node.id.name);
|
|
16307
17161
|
if (internal !== null) classVariables.add(internal);
|
|
16308
17162
|
}
|
|
16309
|
-
if (node.type ===
|
|
16310
|
-
const outer =
|
|
17163
|
+
if (node.type === import_utils91.AST_NODE_TYPES.ClassExpression && node.parent.type === import_utils91.AST_NODE_TYPES.VariableDeclarator && node.parent.id.type === import_utils91.AST_NODE_TYPES.Identifier) {
|
|
17164
|
+
const outer = import_utils91.ASTUtils.findVariable(context.sourceCode.getScope(node.parent), node.parent.id.name);
|
|
16311
17165
|
if (outer !== null) classVariables.add(outer);
|
|
16312
17166
|
}
|
|
16313
17167
|
for (const method of methods) {
|
|
@@ -16323,27 +17177,27 @@ function classScope(context, node, computedReferenceNames) {
|
|
|
16323
17177
|
}
|
|
16324
17178
|
const thisValue = (value) => {
|
|
16325
17179
|
let current = value;
|
|
16326
|
-
while (current?.type ===
|
|
16327
|
-
return current?.type ===
|
|
17180
|
+
while (current?.type === import_utils91.AST_NODE_TYPES.TSAsExpression || current?.type === import_utils91.AST_NODE_TYPES.TSSatisfiesExpression || current?.type === import_utils91.AST_NODE_TYPES.TSNonNullExpression) current = current.expression;
|
|
17181
|
+
return current?.type === import_utils91.AST_NODE_TYPES.ThisExpression;
|
|
16328
17182
|
};
|
|
16329
17183
|
const collectAlias = (current, nestedFunction) => {
|
|
16330
|
-
if (nestedFunction || current.type !==
|
|
16331
|
-
if (current.type ===
|
|
16332
|
-
const binding = current.type ===
|
|
16333
|
-
const value = current.type ===
|
|
17184
|
+
if (nestedFunction || current.type !== import_utils91.AST_NODE_TYPES.VariableDeclarator && current.type !== import_utils91.AST_NODE_TYPES.AssignmentPattern) return;
|
|
17185
|
+
if (current.type === import_utils91.AST_NODE_TYPES.VariableDeclarator && (current.parent.type !== import_utils91.AST_NODE_TYPES.VariableDeclaration || current.parent.kind !== "const")) return;
|
|
17186
|
+
const binding = current.type === import_utils91.AST_NODE_TYPES.VariableDeclarator ? current.id : current.left;
|
|
17187
|
+
const value = current.type === import_utils91.AST_NODE_TYPES.VariableDeclarator ? current.init : current.right;
|
|
16334
17188
|
if (!thisValue(value)) return;
|
|
16335
|
-
if (binding.type ===
|
|
17189
|
+
if (binding.type === import_utils91.AST_NODE_TYPES.ObjectPattern) {
|
|
16336
17190
|
for (const property of binding.properties) {
|
|
16337
|
-
if (property.type ===
|
|
17191
|
+
if (property.type === import_utils91.AST_NODE_TYPES.RestElement) {
|
|
16338
17192
|
for (const name of privateNames) pinned.add(name);
|
|
16339
|
-
} else if (property.key.type ===
|
|
17193
|
+
} else if (property.key.type === import_utils91.AST_NODE_TYPES.Identifier && privateNames.has(property.key.name)) {
|
|
16340
17194
|
pinned.add(property.key.name);
|
|
16341
17195
|
}
|
|
16342
17196
|
}
|
|
16343
17197
|
return;
|
|
16344
17198
|
}
|
|
16345
|
-
if (binding.type !==
|
|
16346
|
-
const variable =
|
|
17199
|
+
if (binding.type !== import_utils91.AST_NODE_TYPES.Identifier) return;
|
|
17200
|
+
const variable = import_utils91.ASTUtils.findVariable(context.sourceCode.getScope(binding), binding.name);
|
|
16347
17201
|
if (variable !== null) {
|
|
16348
17202
|
methodClassVariables.add(variable);
|
|
16349
17203
|
methodAliases.add(variable);
|
|
@@ -16356,16 +17210,16 @@ function classScope(context, node, computedReferenceNames) {
|
|
|
16356
17210
|
walk2(statement, context.sourceCode.visitorKeys, collectAlias);
|
|
16357
17211
|
}
|
|
16358
17212
|
const visitCall = (current, nestedFunction) => {
|
|
16359
|
-
if (current.type ===
|
|
17213
|
+
if (current.type === import_utils91.AST_NODE_TYPES.VariableDeclarator && current.id.type === import_utils91.AST_NODE_TYPES.ObjectPattern && thisValue(current.init)) {
|
|
16360
17214
|
for (const property of current.id.properties) {
|
|
16361
|
-
if (property.type ===
|
|
17215
|
+
if (property.type === import_utils91.AST_NODE_TYPES.RestElement) {
|
|
16362
17216
|
for (const name of privateNames) pinned.add(name);
|
|
16363
17217
|
continue;
|
|
16364
17218
|
}
|
|
16365
|
-
if (property.type ===
|
|
17219
|
+
if (property.type === import_utils91.AST_NODE_TYPES.Property && property.key.type === import_utils91.AST_NODE_TYPES.Identifier && privateNames.has(property.key.name)) pinned.add(property.key.name);
|
|
16366
17220
|
}
|
|
16367
17221
|
}
|
|
16368
|
-
if (current.type !==
|
|
17222
|
+
if (current.type !== import_utils91.AST_NODE_TYPES.MemberExpression) return;
|
|
16369
17223
|
const target = referencedMethod(context, current, methodClassVariables);
|
|
16370
17224
|
if (target === null) {
|
|
16371
17225
|
const possibleTarget = referencedPropertyName(current);
|
|
@@ -16373,12 +17227,12 @@ function classScope(context, node, computedReferenceNames) {
|
|
|
16373
17227
|
return;
|
|
16374
17228
|
}
|
|
16375
17229
|
if (!privateNames.has(target)) return;
|
|
16376
|
-
const objectVariable = current.object.type ===
|
|
17230
|
+
const objectVariable = current.object.type === import_utils91.AST_NODE_TYPES.Identifier ? import_utils91.ASTUtils.findVariable(context.sourceCode.getScope(current.object), current.object.name) : null;
|
|
16377
17231
|
if (objectVariable !== null && methodAliases.has(objectVariable)) {
|
|
16378
17232
|
pinned.add(target);
|
|
16379
17233
|
return;
|
|
16380
17234
|
}
|
|
16381
|
-
if (current.computed || nestedFunction || parameterDecoratorNodes.has(current) || current.parent.type !==
|
|
17235
|
+
if (current.computed || nestedFunction || parameterDecoratorNodes.has(current) || current.parent.type !== import_utils91.AST_NODE_TYPES.CallExpression || current.parent.callee !== current) {
|
|
16382
17236
|
pinned.add(target);
|
|
16383
17237
|
return;
|
|
16384
17238
|
}
|
|
@@ -16398,9 +17252,9 @@ function classScope(context, node, computedReferenceNames) {
|
|
|
16398
17252
|
}
|
|
16399
17253
|
}
|
|
16400
17254
|
for (const member of node.body.body) {
|
|
16401
|
-
if (member.type ===
|
|
17255
|
+
if (member.type === import_utils91.AST_NODE_TYPES.MethodDefinition || member.type === import_utils91.AST_NODE_TYPES.TSAbstractMethodDefinition) continue;
|
|
16402
17256
|
walk2(member, context.sourceCode.visitorKeys, (current) => {
|
|
16403
|
-
if (current.type !==
|
|
17257
|
+
if (current.type !== import_utils91.AST_NODE_TYPES.MemberExpression) return;
|
|
16404
17258
|
const target = referencedMethod(context, current, classVariables);
|
|
16405
17259
|
const possibleTarget = target ?? referencedPropertyName(current);
|
|
16406
17260
|
if (possibleTarget !== null && privateNames.has(possibleTarget)) pinned.add(possibleTarget);
|
|
@@ -16452,12 +17306,12 @@ function classScope(context, node, computedReferenceNames) {
|
|
|
16452
17306
|
}
|
|
16453
17307
|
function isClassRuntimeBarrier(member) {
|
|
16454
17308
|
switch (member.type) {
|
|
16455
|
-
case
|
|
17309
|
+
case import_utils91.AST_NODE_TYPES.StaticBlock:
|
|
16456
17310
|
return true;
|
|
16457
|
-
case
|
|
16458
|
-
case
|
|
17311
|
+
case import_utils91.AST_NODE_TYPES.PropertyDefinition:
|
|
17312
|
+
case import_utils91.AST_NODE_TYPES.AccessorProperty:
|
|
16459
17313
|
return member.static || member.computed || member.decorators.length > 0 || member.value !== null;
|
|
16460
|
-
case
|
|
17314
|
+
case import_utils91.AST_NODE_TYPES.MethodDefinition:
|
|
16461
17315
|
return member.computed || member.decorators.length > 0;
|
|
16462
17316
|
default:
|
|
16463
17317
|
return false;
|
|
@@ -16490,7 +17344,7 @@ var stepdown_default = createRule({
|
|
|
16490
17344
|
moduleScope(context, program);
|
|
16491
17345
|
const computedReferenceNames = /* @__PURE__ */ new Set();
|
|
16492
17346
|
walk2(program, context.sourceCode.visitorKeys, (node) => {
|
|
16493
|
-
if (node.type ===
|
|
17347
|
+
if (node.type === import_utils91.AST_NODE_TYPES.MemberExpression && node.computed && node.property.type === import_utils91.AST_NODE_TYPES.Literal && typeof node.property.value === "string") computedReferenceNames.add(node.property.value);
|
|
16494
17348
|
});
|
|
16495
17349
|
for (const node of classes) classScope(context, node, computedReferenceNames);
|
|
16496
17350
|
}
|
|
@@ -16499,7 +17353,7 @@ var stepdown_default = createRule({
|
|
|
16499
17353
|
});
|
|
16500
17354
|
|
|
16501
17355
|
// src/rules/source-coupled-test.ts
|
|
16502
|
-
var
|
|
17356
|
+
var import_utils92 = require("@typescript-eslint/utils");
|
|
16503
17357
|
var GENERAL_SOURCE_SUFFIX_RE = /\.(?:bash|sh|ya?ml|jsonc|py|[cm]?[jt]s)$/iu;
|
|
16504
17358
|
var FS_MODULES = /* @__PURE__ */ new Set(["fs", "node:fs", "fs/promises", "node:fs/promises"]);
|
|
16505
17359
|
var FS_READERS = /* @__PURE__ */ new Set(["readFile", "readFileSync"]);
|
|
@@ -16568,28 +17422,28 @@ var SOURCE_COUPLED_TEST_DOCUMENTATION = {
|
|
|
16568
17422
|
]
|
|
16569
17423
|
};
|
|
16570
17424
|
function staticMemberName7(node) {
|
|
16571
|
-
if (!node.computed && node.property.type ===
|
|
16572
|
-
if (node.computed && node.property.type ===
|
|
17425
|
+
if (!node.computed && node.property.type === import_utils92.AST_NODE_TYPES.Identifier) return node.property.name;
|
|
17426
|
+
if (node.computed && node.property.type === import_utils92.AST_NODE_TYPES.Literal && typeof node.property.value === "string") return node.property.value;
|
|
16573
17427
|
return null;
|
|
16574
17428
|
}
|
|
16575
|
-
function
|
|
16576
|
-
if (node.type ===
|
|
16577
|
-
if (node.type ===
|
|
16578
|
-
if (node.type ===
|
|
17429
|
+
function unwrap6(node) {
|
|
17430
|
+
if (node.type === import_utils92.AST_NODE_TYPES.AwaitExpression) return unwrap6(node.argument);
|
|
17431
|
+
if (node.type === import_utils92.AST_NODE_TYPES.ChainExpression) return unwrap6(node.expression);
|
|
17432
|
+
if (node.type === import_utils92.AST_NODE_TYPES.TSAsExpression || node.type === import_utils92.AST_NODE_TYPES.TSNonNullExpression || node.type === import_utils92.AST_NODE_TYPES.TSTypeAssertion) return unwrap6(node.expression);
|
|
16579
17433
|
return node;
|
|
16580
17434
|
}
|
|
16581
17435
|
function stringValue(node) {
|
|
16582
|
-
const current =
|
|
16583
|
-
if (current.type ===
|
|
16584
|
-
if (current.type ===
|
|
17436
|
+
const current = unwrap6(node);
|
|
17437
|
+
if (current.type === import_utils92.AST_NODE_TYPES.Literal && typeof current.value === "string") return current.value;
|
|
17438
|
+
if (current.type === import_utils92.AST_NODE_TYPES.TemplateLiteral && current.expressions.length === 0) return current.quasis[0]?.value.cooked ?? null;
|
|
16585
17439
|
return null;
|
|
16586
17440
|
}
|
|
16587
17441
|
function importSource(node) {
|
|
16588
17442
|
return typeof node.source.value === "string" ? node.source.value : null;
|
|
16589
17443
|
}
|
|
16590
17444
|
function requireSource(node) {
|
|
16591
|
-
const current =
|
|
16592
|
-
if (current.type !==
|
|
17445
|
+
const current = unwrap6(node);
|
|
17446
|
+
if (current.type !== import_utils92.AST_NODE_TYPES.CallExpression || current.callee.type !== import_utils92.AST_NODE_TYPES.Identifier || current.callee.name !== "require" || current.arguments.length !== 1 || current.arguments[0]?.type === import_utils92.AST_NODE_TYPES.SpreadElement) return null;
|
|
16593
17447
|
return stringValue(current.arguments[0]);
|
|
16594
17448
|
}
|
|
16595
17449
|
function newScope() {
|
|
@@ -16626,80 +17480,80 @@ function createSourceCoupledRule(name, documentation, sourceSuffixRe) {
|
|
|
16626
17480
|
return /* @__PURE__ */ new Set();
|
|
16627
17481
|
};
|
|
16628
17482
|
const sourcePath = (node) => {
|
|
16629
|
-
const current =
|
|
17483
|
+
const current = unwrap6(node);
|
|
16630
17484
|
const value = stringValue(current);
|
|
16631
17485
|
if (value !== null) return sourceSuffixRe.test(value);
|
|
16632
|
-
if (current.type ===
|
|
16633
|
-
if (current.type ===
|
|
17486
|
+
if (current.type === import_utils92.AST_NODE_TYPES.Identifier) return visible("paths", current.name);
|
|
17487
|
+
if (current.type === import_utils92.AST_NODE_TYPES.BinaryExpression && current.operator === "+") {
|
|
16634
17488
|
return sourcePath(current.left) || sourcePath(current.right);
|
|
16635
17489
|
}
|
|
16636
|
-
if (current.type ===
|
|
16637
|
-
if (current.type ===
|
|
16638
|
-
return current.arguments.some((argument) => argument.type !==
|
|
17490
|
+
if (current.type === import_utils92.AST_NODE_TYPES.TemplateLiteral) return current.expressions.some(sourcePath);
|
|
17491
|
+
if (current.type === import_utils92.AST_NODE_TYPES.CallExpression || current.type === import_utils92.AST_NODE_TYPES.NewExpression) {
|
|
17492
|
+
return current.arguments.some((argument) => argument.type !== import_utils92.AST_NODE_TYPES.SpreadElement && sourcePath(argument));
|
|
16639
17493
|
}
|
|
16640
|
-
if (current.type ===
|
|
17494
|
+
if (current.type === import_utils92.AST_NODE_TYPES.MemberExpression) return sourcePath(current.object);
|
|
16641
17495
|
return false;
|
|
16642
17496
|
};
|
|
16643
17497
|
const rawRead = (node) => {
|
|
16644
|
-
const current =
|
|
16645
|
-
if (current.type !==
|
|
16646
|
-
const callee =
|
|
16647
|
-
if (callee.type ===
|
|
17498
|
+
const current = unwrap6(node);
|
|
17499
|
+
if (current.type !== import_utils92.AST_NODE_TYPES.CallExpression || current.arguments.length === 0) return false;
|
|
17500
|
+
const callee = unwrap6(current.callee);
|
|
17501
|
+
if (callee.type === import_utils92.AST_NODE_TYPES.Identifier) {
|
|
16648
17502
|
return visible("fsReaders", callee.name) && sourcePath(current.arguments[0]);
|
|
16649
17503
|
}
|
|
16650
|
-
if (callee.type !==
|
|
17504
|
+
if (callee.type !== import_utils92.AST_NODE_TYPES.MemberExpression) return false;
|
|
16651
17505
|
const name2 = staticMemberName7(callee);
|
|
16652
|
-
const object =
|
|
16653
|
-
return name2 !== null && FS_READERS.has(name2) && object.type ===
|
|
17506
|
+
const object = unwrap6(callee.object);
|
|
17507
|
+
return name2 !== null && FS_READERS.has(name2) && object.type === import_utils92.AST_NODE_TYPES.Identifier && visible("fsObjects", object.name) && sourcePath(current.arguments[0]);
|
|
16654
17508
|
};
|
|
16655
17509
|
const rawOrigins = (node) => {
|
|
16656
|
-
const current =
|
|
16657
|
-
if (current.type ===
|
|
17510
|
+
const current = unwrap6(node);
|
|
17511
|
+
if (current.type === import_utils92.AST_NODE_TYPES.Identifier) return visibleRawOrigins(current.name);
|
|
16658
17512
|
if (rawRead(current)) return /* @__PURE__ */ new Set([`${current.range[0]}:${current.range[1]}`]);
|
|
16659
|
-
if (current.type ===
|
|
16660
|
-
if (current.type ===
|
|
16661
|
-
if (current.type !==
|
|
16662
|
-
const callee =
|
|
16663
|
-
if (callee.type !==
|
|
17513
|
+
if (current.type === import_utils92.AST_NODE_TYPES.BinaryExpression && current.operator === "+") return /* @__PURE__ */ new Set([...rawOrigins(current.left), ...rawOrigins(current.right)]);
|
|
17514
|
+
if (current.type === import_utils92.AST_NODE_TYPES.MemberExpression && staticMemberName7(current) === "length") return rawOrigins(current.object);
|
|
17515
|
+
if (current.type !== import_utils92.AST_NODE_TYPES.CallExpression) return /* @__PURE__ */ new Set();
|
|
17516
|
+
const callee = unwrap6(current.callee);
|
|
17517
|
+
if (callee.type !== import_utils92.AST_NODE_TYPES.MemberExpression) return /* @__PURE__ */ new Set();
|
|
16664
17518
|
const name2 = staticMemberName7(callee);
|
|
16665
17519
|
return name2 !== null && TEXT_TRANSFORMS.has(name2) ? rawOrigins(callee.object) : /* @__PURE__ */ new Set();
|
|
16666
17520
|
};
|
|
16667
17521
|
const evidenceOrigins = (node) => {
|
|
16668
|
-
const current =
|
|
17522
|
+
const current = unwrap6(node);
|
|
16669
17523
|
const direct = rawOrigins(current);
|
|
16670
17524
|
if (direct.size > 0) return direct;
|
|
16671
|
-
if (current.type ===
|
|
16672
|
-
if (current.type ===
|
|
16673
|
-
if (current.type !==
|
|
16674
|
-
const callee =
|
|
16675
|
-
if (callee.type !==
|
|
17525
|
+
if (current.type === import_utils92.AST_NODE_TYPES.BinaryExpression || current.type === import_utils92.AST_NODE_TYPES.LogicalExpression) return /* @__PURE__ */ new Set([...evidenceOrigins(current.left), ...evidenceOrigins(current.right)]);
|
|
17526
|
+
if (current.type === import_utils92.AST_NODE_TYPES.UnaryExpression) return evidenceOrigins(current.argument);
|
|
17527
|
+
if (current.type !== import_utils92.AST_NODE_TYPES.CallExpression) return /* @__PURE__ */ new Set();
|
|
17528
|
+
const callee = unwrap6(current.callee);
|
|
17529
|
+
if (callee.type !== import_utils92.AST_NODE_TYPES.MemberExpression) return /* @__PURE__ */ new Set();
|
|
16676
17530
|
const name2 = staticMemberName7(callee);
|
|
16677
17531
|
if (name2 !== null && TEXT_PREDICATES.has(name2)) return rawOrigins(callee.object);
|
|
16678
|
-
if (name2 !== null && REGEXP_PREDICATES.has(name2)) return new Set(current.arguments.flatMap((argument) => argument.type ===
|
|
17532
|
+
if (name2 !== null && REGEXP_PREDICATES.has(name2)) return new Set(current.arguments.flatMap((argument) => argument.type === import_utils92.AST_NODE_TYPES.SpreadElement ? [] : [...rawOrigins(argument)]));
|
|
16679
17533
|
return /* @__PURE__ */ new Set();
|
|
16680
17534
|
};
|
|
16681
17535
|
const rawAssertionOrigins = (node) => {
|
|
16682
|
-
const callee =
|
|
16683
|
-
if (callee.type ===
|
|
16684
|
-
return new Set(node.arguments.flatMap((argument) => argument.type ===
|
|
17536
|
+
const callee = unwrap6(node.callee);
|
|
17537
|
+
if (callee.type === import_utils92.AST_NODE_TYPES.Identifier && callee.name === "assert") {
|
|
17538
|
+
return new Set(node.arguments.flatMap((argument) => argument.type === import_utils92.AST_NODE_TYPES.SpreadElement ? [] : [...evidenceOrigins(argument)]));
|
|
16685
17539
|
}
|
|
16686
|
-
if (callee.type !==
|
|
17540
|
+
if (callee.type !== import_utils92.AST_NODE_TYPES.MemberExpression) return /* @__PURE__ */ new Set();
|
|
16687
17541
|
const matcher = staticMemberName7(callee);
|
|
16688
17542
|
if (matcher === null) return /* @__PURE__ */ new Set();
|
|
16689
|
-
let receiver =
|
|
16690
|
-
while (receiver.type ===
|
|
16691
|
-
if (receiver.type ===
|
|
17543
|
+
let receiver = unwrap6(callee.object);
|
|
17544
|
+
while (receiver.type === import_utils92.AST_NODE_TYPES.MemberExpression && EXPECT_MODIFIERS2.has(staticMemberName7(receiver) ?? "")) receiver = unwrap6(receiver.object);
|
|
17545
|
+
if (receiver.type === import_utils92.AST_NODE_TYPES.CallExpression && receiver.callee.type === import_utils92.AST_NODE_TYPES.Identifier && receiver.callee.name === "expect") {
|
|
16692
17546
|
if (!EXPECT_MATCHERS.has(matcher)) return /* @__PURE__ */ new Set();
|
|
16693
|
-
return new Set([...receiver.arguments, ...node.arguments].flatMap((argument) => argument.type ===
|
|
17547
|
+
return new Set([...receiver.arguments, ...node.arguments].flatMap((argument) => argument.type === import_utils92.AST_NODE_TYPES.SpreadElement ? [] : [...evidenceOrigins(argument)]));
|
|
16694
17548
|
}
|
|
16695
|
-
if (receiver.type !==
|
|
16696
|
-
return new Set(node.arguments.flatMap((argument) => argument.type ===
|
|
17549
|
+
if (receiver.type !== import_utils92.AST_NODE_TYPES.Identifier || receiver.name !== "assert" || !ASSERT_MATCHERS.has(matcher)) return /* @__PURE__ */ new Set();
|
|
17550
|
+
return new Set(node.arguments.flatMap((argument) => argument.type === import_utils92.AST_NODE_TYPES.SpreadElement ? [] : [...evidenceOrigins(argument)]));
|
|
16697
17551
|
};
|
|
16698
17552
|
const rawRegexExtractionOrigins = (node) => {
|
|
16699
|
-
const callee =
|
|
16700
|
-
if (callee.type !==
|
|
17553
|
+
const callee = unwrap6(node.callee);
|
|
17554
|
+
if (callee.type !== import_utils92.AST_NODE_TYPES.MemberExpression || staticMemberName7(callee) !== "matchAll" || node.arguments.length !== 1) return /* @__PURE__ */ new Set();
|
|
16701
17555
|
const argument = node.arguments[0];
|
|
16702
|
-
if (argument?.type !==
|
|
17556
|
+
if (argument?.type !== import_utils92.AST_NODE_TYPES.Literal || !(argument.value instanceof RegExp)) return /* @__PURE__ */ new Set();
|
|
16703
17557
|
return rawOrigins(callee.object);
|
|
16704
17558
|
};
|
|
16705
17559
|
const declare = (name2, state) => {
|
|
@@ -16719,16 +17573,16 @@ function createSourceCoupledRule(name, documentation, sourceSuffixRe) {
|
|
|
16719
17573
|
}
|
|
16720
17574
|
};
|
|
16721
17575
|
const sourceCollection = (node) => {
|
|
16722
|
-
const current =
|
|
16723
|
-
return current.type ===
|
|
17576
|
+
const current = unwrap6(node);
|
|
17577
|
+
return current.type === import_utils92.AST_NODE_TYPES.ArrayExpression && current.elements.length > 0 && current.elements.every((element) => element !== null && element.type !== import_utils92.AST_NODE_TYPES.SpreadElement && sourcePath(element));
|
|
16724
17578
|
};
|
|
16725
17579
|
const declaredNames2 = (node) => {
|
|
16726
|
-
const current =
|
|
16727
|
-
if (current.type ===
|
|
16728
|
-
if (current.type ===
|
|
16729
|
-
if (current.type ===
|
|
16730
|
-
if (current.type ===
|
|
16731
|
-
if (current.type ===
|
|
17580
|
+
const current = unwrap6(node);
|
|
17581
|
+
if (current.type === import_utils92.AST_NODE_TYPES.Identifier) return [current.name];
|
|
17582
|
+
if (current.type === import_utils92.AST_NODE_TYPES.AssignmentPattern) return declaredNames2(current.left);
|
|
17583
|
+
if (current.type === import_utils92.AST_NODE_TYPES.RestElement) return declaredNames2(current.argument);
|
|
17584
|
+
if (current.type === import_utils92.AST_NODE_TYPES.ArrayPattern) return current.elements.flatMap((element) => element === null ? [] : declaredNames2(element));
|
|
17585
|
+
if (current.type === import_utils92.AST_NODE_TYPES.ObjectPattern) return current.properties.flatMap((property) => property.type === import_utils92.AST_NODE_TYPES.RestElement ? declaredNames2(property.argument) : declaredNames2(property.value));
|
|
16732
17586
|
return [];
|
|
16733
17587
|
};
|
|
16734
17588
|
const enterFunction = (node) => {
|
|
@@ -16743,8 +17597,8 @@ function createSourceCoupledRule(name, documentation, sourceSuffixRe) {
|
|
|
16743
17597
|
const source = importSource(node);
|
|
16744
17598
|
if (source === null || !FS_MODULES.has(source)) return;
|
|
16745
17599
|
for (const specifier of node.specifiers) {
|
|
16746
|
-
if (specifier.type ===
|
|
16747
|
-
const imported = specifier.imported.type ===
|
|
17600
|
+
if (specifier.type === import_utils92.AST_NODE_TYPES.ImportSpecifier) {
|
|
17601
|
+
const imported = specifier.imported.type === import_utils92.AST_NODE_TYPES.Identifier ? specifier.imported.name : String(specifier.imported.value);
|
|
16748
17602
|
if (FS_READERS.has(imported)) declare(specifier.local.name, { fsReader: true });
|
|
16749
17603
|
} else {
|
|
16750
17604
|
declare(specifier.local.name, { fsObject: true });
|
|
@@ -16756,29 +17610,29 @@ function createSourceCoupledRule(name, documentation, sourceSuffixRe) {
|
|
|
16756
17610
|
VariableDeclarator(node) {
|
|
16757
17611
|
if (node.init === null) return;
|
|
16758
17612
|
const required = requireSource(node.init);
|
|
16759
|
-
if (required !== null && FS_MODULES.has(required) && node.id.type ===
|
|
17613
|
+
if (required !== null && FS_MODULES.has(required) && node.id.type === import_utils92.AST_NODE_TYPES.Identifier) {
|
|
16760
17614
|
declare(node.id.name, { fsObject: true });
|
|
16761
17615
|
return;
|
|
16762
17616
|
}
|
|
16763
|
-
if (node.id.type ===
|
|
17617
|
+
if (node.id.type === import_utils92.AST_NODE_TYPES.ObjectPattern && required !== null && FS_MODULES.has(required)) {
|
|
16764
17618
|
for (const property of node.id.properties) {
|
|
16765
|
-
if (property.type !==
|
|
16766
|
-
const key = property.key.type ===
|
|
17619
|
+
if (property.type !== import_utils92.AST_NODE_TYPES.Property || property.value.type !== import_utils92.AST_NODE_TYPES.Identifier) continue;
|
|
17620
|
+
const key = property.key.type === import_utils92.AST_NODE_TYPES.Identifier ? property.key.name : property.key.type === import_utils92.AST_NODE_TYPES.Literal ? String(property.key.value) : "";
|
|
16767
17621
|
if (FS_READERS.has(key)) declare(property.value.name, { fsReader: true });
|
|
16768
17622
|
}
|
|
16769
17623
|
return;
|
|
16770
17624
|
}
|
|
16771
|
-
if (node.id.type !==
|
|
17625
|
+
if (node.id.type !== import_utils92.AST_NODE_TYPES.Identifier) return;
|
|
16772
17626
|
declare(node.id.name, { collection: sourceCollection(node.init), path: sourcePath(node.init), rawOrigins: rawOrigins(node.init) });
|
|
16773
17627
|
},
|
|
16774
17628
|
AssignmentExpression(node) {
|
|
16775
|
-
if (node.left.type ===
|
|
17629
|
+
if (node.left.type === import_utils92.AST_NODE_TYPES.Identifier) declare(node.left.name, { path: sourcePath(node.right), rawOrigins: rawOrigins(node.right) });
|
|
16776
17630
|
},
|
|
16777
17631
|
ForOfStatement(node) {
|
|
16778
|
-
const right =
|
|
16779
|
-
const collection = right.type ===
|
|
16780
|
-
const left = node.left.type ===
|
|
16781
|
-
if (collection && left?.type ===
|
|
17632
|
+
const right = unwrap6(node.right);
|
|
17633
|
+
const collection = right.type === import_utils92.AST_NODE_TYPES.Identifier && visible("collections", right.name);
|
|
17634
|
+
const left = node.left.type === import_utils92.AST_NODE_TYPES.VariableDeclaration ? node.left.declarations[0]?.id : node.left;
|
|
17635
|
+
if (collection && left?.type === import_utils92.AST_NODE_TYPES.Identifier) declare(left.name, { path: true });
|
|
16782
17636
|
},
|
|
16783
17637
|
CallExpression(node) {
|
|
16784
17638
|
const origins = /* @__PURE__ */ new Set([
|
|
@@ -16799,6 +17653,120 @@ var source_coupled_test_default = createSourceCoupledRule(
|
|
|
16799
17653
|
GENERAL_SOURCE_SUFFIX_RE
|
|
16800
17654
|
);
|
|
16801
17655
|
|
|
17656
|
+
// src/rules/sole-export-matches-filename.ts
|
|
17657
|
+
var import_utils93 = require("@typescript-eslint/utils");
|
|
17658
|
+
var SOLE_EXPORT_MATCHES_FILENAME_DOCUMENTATION = {
|
|
17659
|
+
summary: "Match a module filename to its sole named public runtime export.",
|
|
17660
|
+
rationale: "When a module owns one runtime responsibility, matching names make that responsibility directly discoverable.",
|
|
17661
|
+
remediation: "Rename the module stem to the kebab-case export name, or colocate genuinely related exports.",
|
|
17662
|
+
category: "maintainability",
|
|
17663
|
+
limitations: [
|
|
17664
|
+
"Framework entrypoints, generic stems covered by no-generic-single-export-module, tests, generated files, anonymous defaults, CommonJS, and re-exports are excluded.",
|
|
17665
|
+
"The rule compares the primary filename stem and preserves conventional suffixes such as .server or .worker."
|
|
17666
|
+
],
|
|
17667
|
+
examples: [
|
|
17668
|
+
{ 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 },
|
|
17669
|
+
{ 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 }
|
|
17670
|
+
]
|
|
17671
|
+
};
|
|
17672
|
+
var EXCLUDED_STEMS = /* @__PURE__ */ new Set([
|
|
17673
|
+
"common",
|
|
17674
|
+
"global",
|
|
17675
|
+
"helpers",
|
|
17676
|
+
"index",
|
|
17677
|
+
"layout",
|
|
17678
|
+
"loading",
|
|
17679
|
+
"middleware",
|
|
17680
|
+
"misc",
|
|
17681
|
+
"not-found",
|
|
17682
|
+
"page",
|
|
17683
|
+
"route",
|
|
17684
|
+
"shared",
|
|
17685
|
+
"template",
|
|
17686
|
+
"types",
|
|
17687
|
+
"util",
|
|
17688
|
+
"utils"
|
|
17689
|
+
]);
|
|
17690
|
+
function stem3(filename) {
|
|
17691
|
+
const base = filename.replaceAll("\\", "/").split("/").at(-1) ?? "";
|
|
17692
|
+
return base.replace(/\.[cm]?[jt]sx?$/u, "").split(".")[0] ?? "";
|
|
17693
|
+
}
|
|
17694
|
+
function kebabCase(name) {
|
|
17695
|
+
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();
|
|
17696
|
+
}
|
|
17697
|
+
function declarationExport(statement) {
|
|
17698
|
+
const declaration = statement.declaration;
|
|
17699
|
+
if (declaration === null || declaration.declare === true) return [];
|
|
17700
|
+
if (declaration.type === import_utils93.AST_NODE_TYPES.ClassDeclaration || declaration.type === import_utils93.AST_NODE_TYPES.FunctionDeclaration || declaration.type === import_utils93.AST_NODE_TYPES.TSEnumDeclaration) return declaration.id === null ? [] : [{ name: declaration.id.name, node: declaration }];
|
|
17701
|
+
if (declaration.type !== import_utils93.AST_NODE_TYPES.VariableDeclaration) return [];
|
|
17702
|
+
return declaration.declarations.flatMap(
|
|
17703
|
+
(item) => item.id.type === import_utils93.AST_NODE_TYPES.Identifier ? [{ name: item.id.name, node: item }] : []
|
|
17704
|
+
);
|
|
17705
|
+
}
|
|
17706
|
+
var sole_export_matches_filename_default = createRule({
|
|
17707
|
+
name: "sole-export-matches-filename",
|
|
17708
|
+
documentation: SOLE_EXPORT_MATCHES_FILENAME_DOCUMENTATION,
|
|
17709
|
+
meta: {
|
|
17710
|
+
type: "suggestion",
|
|
17711
|
+
docs: { description: "Match a module filename to its sole named public runtime export." },
|
|
17712
|
+
schema: [],
|
|
17713
|
+
messages: {
|
|
17714
|
+
matchSoleExport: "This module's sole runtime export is `{{exported}}`; rename the file stem to `{{expected}}`."
|
|
17715
|
+
}
|
|
17716
|
+
},
|
|
17717
|
+
defaultOptions: [],
|
|
17718
|
+
create(context) {
|
|
17719
|
+
const fileStem = stem3(context.filename);
|
|
17720
|
+
const normalizedFilename = context.filename.replaceAll("\\", "/");
|
|
17721
|
+
if (EXCLUDED_STEMS.has(fileStem) || normalizedFilename.includes("/pages/") || context.filename.endsWith(".d.ts") || isTestFile(context.filename) || isGeneratedFile(context.filename, context.sourceCode.text)) return {};
|
|
17722
|
+
return {
|
|
17723
|
+
"Program:exit"(program) {
|
|
17724
|
+
const exports2 = [];
|
|
17725
|
+
const publicExports = /* @__PURE__ */ new Set();
|
|
17726
|
+
for (const statement of program.body) {
|
|
17727
|
+
if (statement.type === import_utils93.AST_NODE_TYPES.ExportAllDeclaration || statement.type === import_utils93.AST_NODE_TYPES.ExportNamedDeclaration && statement.source !== null) return;
|
|
17728
|
+
if (statement.type === import_utils93.AST_NODE_TYPES.ExportDefaultDeclaration) {
|
|
17729
|
+
publicExports.add("default");
|
|
17730
|
+
const declaration2 = statement.declaration;
|
|
17731
|
+
if ((declaration2.type === import_utils93.AST_NODE_TYPES.ClassDeclaration || declaration2.type === import_utils93.AST_NODE_TYPES.FunctionDeclaration) && declaration2.id !== null) exports2.push({ name: declaration2.id.name, node: declaration2 });
|
|
17732
|
+
else return;
|
|
17733
|
+
}
|
|
17734
|
+
if (statement.type !== import_utils93.AST_NODE_TYPES.ExportNamedDeclaration) continue;
|
|
17735
|
+
const declaration = statement.declaration;
|
|
17736
|
+
if (declaration !== null && "id" in declaration && declaration.id?.type === import_utils93.AST_NODE_TYPES.Identifier) {
|
|
17737
|
+
publicExports.add(declaration.id.name);
|
|
17738
|
+
}
|
|
17739
|
+
if (declaration?.type === import_utils93.AST_NODE_TYPES.VariableDeclaration) {
|
|
17740
|
+
for (const item of declaration.declarations) {
|
|
17741
|
+
if (item.id.type === import_utils93.AST_NODE_TYPES.Identifier) publicExports.add(item.id.name);
|
|
17742
|
+
}
|
|
17743
|
+
}
|
|
17744
|
+
for (const specifier of statement.specifiers) {
|
|
17745
|
+
const exported = specifier.exported.type === import_utils93.AST_NODE_TYPES.Identifier ? specifier.exported.name : specifier.exported.value;
|
|
17746
|
+
publicExports.add(String(exported));
|
|
17747
|
+
}
|
|
17748
|
+
if (statement.exportKind === "type") continue;
|
|
17749
|
+
exports2.push(...declarationExport(statement));
|
|
17750
|
+
for (const specifier of statement.specifiers) {
|
|
17751
|
+
const exported = specifier.exported.type === import_utils93.AST_NODE_TYPES.Identifier ? specifier.exported.name : specifier.exported.value;
|
|
17752
|
+
publicExports.add(String(exported));
|
|
17753
|
+
if (specifier.exportKind === "type") continue;
|
|
17754
|
+
if (exported === "default") exports2.push({ name: specifier.local.name, node: specifier });
|
|
17755
|
+
else exports2.push({ name: String(exported), node: specifier });
|
|
17756
|
+
}
|
|
17757
|
+
}
|
|
17758
|
+
const unique = new Map(exports2.map((item) => [item.name, item]));
|
|
17759
|
+
if (unique.size !== 1 || publicExports.size !== 1) return;
|
|
17760
|
+
const only = [...unique.values()][0];
|
|
17761
|
+
if (only === void 0) return;
|
|
17762
|
+
const expected = kebabCase(only.name);
|
|
17763
|
+
if (expected === "" || expected === fileStem.toLowerCase()) return;
|
|
17764
|
+
context.report({ node: only.node, messageId: "matchSoleExport", data: { exported: only.name, expected } });
|
|
17765
|
+
}
|
|
17766
|
+
};
|
|
17767
|
+
}
|
|
17768
|
+
});
|
|
17769
|
+
|
|
16802
17770
|
// src/rules/iac-source-coupled-test.ts
|
|
16803
17771
|
var IAC_SOURCE_SUFFIX_RE = /(?:\.tf\.json|\.tftest\.(?:hcl|json)|\.(?:hcl|tf|tfvars))$/iu;
|
|
16804
17772
|
var IAC_SOURCE_COUPLED_TEST_DOCUMENTATION = {
|
|
@@ -16838,7 +17806,7 @@ var iac_source_coupled_test_default = createSourceCoupledRule(
|
|
|
16838
17806
|
);
|
|
16839
17807
|
|
|
16840
17808
|
// src/rules/require-pascal-case-zod-schema-name.ts
|
|
16841
|
-
var
|
|
17809
|
+
var import_utils94 = require("@typescript-eslint/utils");
|
|
16842
17810
|
var REQUIRE_PASCAL_CASE_ZOD_SCHEMA_NAME_DOCUMENTATION = {
|
|
16843
17811
|
summary: "Require confirmed module-level Zod schema contracts to use PascalCase with a `Schema` suffix.",
|
|
16844
17812
|
rationale: "A reusable Zod schema is a runtime type contract. PascalCase mirrors that role; SCREAMING_SNAKE_CASE should remain reserved for scalar values and lookup tables.",
|
|
@@ -16970,18 +17938,18 @@ var SCHEMA_RETURNING_METHODS = /* @__PURE__ */ new Set([
|
|
|
16970
17938
|
"superRefine",
|
|
16971
17939
|
"transform"
|
|
16972
17940
|
]);
|
|
16973
|
-
var terminalMethodName = (callee) => !callee.computed && callee.property.type ===
|
|
17941
|
+
var terminalMethodName = (callee) => !callee.computed && callee.property.type === import_utils94.AST_NODE_TYPES.Identifier ? callee.property.name : null;
|
|
16974
17942
|
var calleeChainRoot = (node) => {
|
|
16975
17943
|
let current = node;
|
|
16976
17944
|
for (; ; ) {
|
|
16977
|
-
if (current.type ===
|
|
17945
|
+
if (current.type === import_utils94.AST_NODE_TYPES.Identifier) {
|
|
16978
17946
|
return current;
|
|
16979
17947
|
}
|
|
16980
|
-
if (current.type ===
|
|
17948
|
+
if (current.type === import_utils94.AST_NODE_TYPES.MemberExpression) {
|
|
16981
17949
|
current = current.object;
|
|
16982
17950
|
continue;
|
|
16983
17951
|
}
|
|
16984
|
-
if (current.type ===
|
|
17952
|
+
if (current.type === import_utils94.AST_NODE_TYPES.CallExpression) {
|
|
16985
17953
|
current = current.callee;
|
|
16986
17954
|
continue;
|
|
16987
17955
|
}
|
|
@@ -16992,13 +17960,13 @@ var chainMemberNames = (node) => {
|
|
|
16992
17960
|
const names = [];
|
|
16993
17961
|
let current = node;
|
|
16994
17962
|
for (; ; ) {
|
|
16995
|
-
if (current.type ===
|
|
16996
|
-
if (current.computed || current.property.type !==
|
|
17963
|
+
if (current.type === import_utils94.AST_NODE_TYPES.MemberExpression) {
|
|
17964
|
+
if (current.computed || current.property.type !== import_utils94.AST_NODE_TYPES.Identifier) return [];
|
|
16997
17965
|
names.push(current.property.name);
|
|
16998
17966
|
current = current.object;
|
|
16999
17967
|
continue;
|
|
17000
17968
|
}
|
|
17001
|
-
if (current.type ===
|
|
17969
|
+
if (current.type === import_utils94.AST_NODE_TYPES.CallExpression) {
|
|
17002
17970
|
current = current.callee;
|
|
17003
17971
|
continue;
|
|
17004
17972
|
}
|
|
@@ -17009,16 +17977,16 @@ var chainMemberNames = (node) => {
|
|
|
17009
17977
|
};
|
|
17010
17978
|
var unwrapExpression4 = (node) => {
|
|
17011
17979
|
let current = node;
|
|
17012
|
-
while (current.type ===
|
|
17980
|
+
while (current.type === import_utils94.AST_NODE_TYPES.TSAsExpression || current.type === import_utils94.AST_NODE_TYPES.TSSatisfiesExpression || current.type === import_utils94.AST_NODE_TYPES.TSNonNullExpression || current.type === import_utils94.AST_NODE_TYPES.TSTypeAssertion) {
|
|
17013
17981
|
current = current.expression;
|
|
17014
17982
|
}
|
|
17015
17983
|
return current;
|
|
17016
17984
|
};
|
|
17017
17985
|
var isModuleDeclarator = (node) => {
|
|
17018
17986
|
const declaration = node.parent;
|
|
17019
|
-
if (declaration.type !==
|
|
17987
|
+
if (declaration.type !== import_utils94.AST_NODE_TYPES.VariableDeclaration) return false;
|
|
17020
17988
|
const owner = declaration.parent;
|
|
17021
|
-
return owner.type ===
|
|
17989
|
+
return owner.type === import_utils94.AST_NODE_TYPES.Program || owner.type === import_utils94.AST_NODE_TYPES.ExportNamedDeclaration && owner.parent.type === import_utils94.AST_NODE_TYPES.Program;
|
|
17022
17990
|
};
|
|
17023
17991
|
var require_pascal_case_zod_schema_name_default = createRule({
|
|
17024
17992
|
name: "require-pascal-case-zod-schema-name",
|
|
@@ -17038,7 +18006,7 @@ var require_pascal_case_zod_schema_name_default = createRule({
|
|
|
17038
18006
|
const zodBindings = /* @__PURE__ */ new Set();
|
|
17039
18007
|
const schemaBindings = /* @__PURE__ */ new Set();
|
|
17040
18008
|
function resolvedBinding(identifier) {
|
|
17041
|
-
return
|
|
18009
|
+
return import_utils94.ASTUtils.findVariable(
|
|
17042
18010
|
context.sourceCode.getScope(identifier),
|
|
17043
18011
|
identifier.name
|
|
17044
18012
|
);
|
|
@@ -17059,8 +18027,8 @@ var require_pascal_case_zod_schema_name_default = createRule({
|
|
|
17059
18027
|
}
|
|
17060
18028
|
function isConfirmedSchema(expression) {
|
|
17061
18029
|
const init = unwrapExpression4(expression);
|
|
17062
|
-
if (init.type ===
|
|
17063
|
-
if (init.type !==
|
|
18030
|
+
if (init.type === import_utils94.AST_NODE_TYPES.Identifier) return isSchemaBinding(init);
|
|
18031
|
+
if (init.type !== import_utils94.AST_NODE_TYPES.CallExpression || init.callee.type !== import_utils94.AST_NODE_TYPES.MemberExpression) {
|
|
17064
18032
|
return false;
|
|
17065
18033
|
}
|
|
17066
18034
|
const terminal = terminalMethodName(init.callee);
|
|
@@ -17080,7 +18048,7 @@ var require_pascal_case_zod_schema_name_default = createRule({
|
|
|
17080
18048
|
ImportDeclaration(node) {
|
|
17081
18049
|
if (!isZodModule(node.source.value)) return;
|
|
17082
18050
|
for (const specifier of node.specifiers) {
|
|
17083
|
-
if (specifier.type ===
|
|
18051
|
+
if (specifier.type === import_utils94.AST_NODE_TYPES.ImportNamespaceSpecifier || specifier.type === import_utils94.AST_NODE_TYPES.ImportDefaultSpecifier || specifier.type === import_utils94.AST_NODE_TYPES.ImportSpecifier && (specifier.imported.type === import_utils94.AST_NODE_TYPES.Identifier ? specifier.imported.name === "z" : specifier.imported.value === "z")) {
|
|
17084
18052
|
recordZodBinding(specifier.local);
|
|
17085
18053
|
}
|
|
17086
18054
|
}
|
|
@@ -17089,7 +18057,7 @@ var require_pascal_case_zod_schema_name_default = createRule({
|
|
|
17089
18057
|
if (!isModuleDeclarator(node)) return;
|
|
17090
18058
|
const init = node.init;
|
|
17091
18059
|
if (init === null || init === void 0) return;
|
|
17092
|
-
if (node.id.type !==
|
|
18060
|
+
if (node.id.type !== import_utils94.AST_NODE_TYPES.Identifier) return;
|
|
17093
18061
|
if (!isConfirmedSchema(init)) return;
|
|
17094
18062
|
const binding = resolvedBinding(node.id);
|
|
17095
18063
|
if (binding !== null) schemaBindings.add(binding);
|
|
@@ -17247,11 +18215,16 @@ var RULES = {
|
|
|
17247
18215
|
"prefer-shadcn-primitives": prefer_shadcn_primitives_default,
|
|
17248
18216
|
"prefer-module-level-constant": prefer_module_level_constant_default,
|
|
17249
18217
|
"prefer-module-level-schema": prefer_module_level_schema_default,
|
|
18218
|
+
"prefer-named-complex-return-type": prefer_named_complex_return_type_default,
|
|
17250
18219
|
"prefer-native-random-uuid": prefer_native_random_uuid_default,
|
|
18220
|
+
"prefer-node-crypto-hash": prefer_node_crypto_hash_default,
|
|
18221
|
+
"prefer-node-fs-promises": prefer_node_fs_promises_default,
|
|
17251
18222
|
"prefer-non-nullable-collection": prefer_non_nullable_collection_default,
|
|
17252
18223
|
"prefer-nullish-filter-predicate": prefer_nullish_filter_predicate_default,
|
|
17253
18224
|
"prefer-await-in-async-return": prefer_await_in_async_return_default,
|
|
17254
18225
|
"prefer-schema-for-api-payload": prefer_schema_for_api_payload_default,
|
|
18226
|
+
"prefer-shared-zod-enum": prefer_shared_zod_enum_default,
|
|
18227
|
+
"prefer-switch-for-repeated-equality": prefer_switch_for_repeated_equality_default,
|
|
17255
18228
|
"prefer-semantic-colors": prefer_semantic_colors_default,
|
|
17256
18229
|
"prefer-server-actions": prefer_server_actions_default,
|
|
17257
18230
|
"prefer-whole-object-assertion": prefer_whole_object_assertion_default,
|
|
@@ -17259,24 +18232,37 @@ var RULES = {
|
|
|
17259
18232
|
"prefer-zod-infer": prefer_zod_infer_default,
|
|
17260
18233
|
"require-assert-never": require_assert_never_default,
|
|
17261
18234
|
"require-fetch-timeout": require_fetch_timeout_default,
|
|
18235
|
+
"require-interface-for-exported-class": require_interface_for_exported_class_default,
|
|
17262
18236
|
"require-port-for-service": require_port_for_service_default,
|
|
18237
|
+
"require-sql-access-class": require_sql_access_class_default,
|
|
17263
18238
|
"require-static-next-matcher": require_static_next_matcher_default,
|
|
17264
18239
|
"require-zod-form-validation": require_zod_form_validation_default,
|
|
17265
18240
|
"store-insert-requires-on-conflict": store_insert_requires_on_conflict_default,
|
|
17266
18241
|
"stepdown": stepdown_default,
|
|
17267
18242
|
"source-coupled-test": source_coupled_test_default,
|
|
18243
|
+
"sole-export-matches-filename": sole_export_matches_filename_default,
|
|
17268
18244
|
"require-pascal-case-zod-schema-name": require_pascal_case_zod_schema_name_default
|
|
17269
18245
|
};
|
|
17270
18246
|
var meta = {
|
|
17271
18247
|
name: "@sarj/eslint-plugin",
|
|
17272
|
-
version: "15.
|
|
18248
|
+
version: "15.16.0"
|
|
17273
18249
|
};
|
|
17274
18250
|
var APPLICATION_ONLY_RULES = [
|
|
17275
18251
|
"no-restricted-library-load",
|
|
17276
18252
|
"prefer-native-random-uuid",
|
|
17277
18253
|
"prefer-shadcn-primitives"
|
|
17278
18254
|
];
|
|
17279
|
-
var ADVISORY_RULES = [
|
|
18255
|
+
var ADVISORY_RULES = [
|
|
18256
|
+
"@sarj/prefer-named-complex-return-type",
|
|
18257
|
+
"@sarj/prefer-node-crypto-hash",
|
|
18258
|
+
"@sarj/prefer-node-fs-promises",
|
|
18259
|
+
"@sarj/prefer-shared-zod-enum",
|
|
18260
|
+
"@sarj/prefer-switch-for-repeated-equality",
|
|
18261
|
+
"@sarj/require-interface-for-exported-class",
|
|
18262
|
+
"@sarj/require-pascal-case-zod-schema-name",
|
|
18263
|
+
"@sarj/require-sql-access-class",
|
|
18264
|
+
"@sarj/sole-export-matches-filename"
|
|
18265
|
+
];
|
|
17280
18266
|
var RECOMMENDED_RULES = {
|
|
17281
18267
|
"@sarj/interface-contract-members-private": "error",
|
|
17282
18268
|
"@sarj/iac-source-coupled-test": "error",
|
|
@@ -17330,10 +18316,15 @@ var RECOMMENDED_RULES = {
|
|
|
17330
18316
|
"@sarj/prefer-immutable-module-constant": "error",
|
|
17331
18317
|
"@sarj/prefer-module-level-constant": "error",
|
|
17332
18318
|
"@sarj/prefer-module-level-schema": "error",
|
|
18319
|
+
"@sarj/prefer-named-complex-return-type": "warn",
|
|
18320
|
+
"@sarj/prefer-node-crypto-hash": "warn",
|
|
18321
|
+
"@sarj/prefer-node-fs-promises": "warn",
|
|
17333
18322
|
"@sarj/prefer-non-nullable-collection": "error",
|
|
17334
18323
|
"@sarj/prefer-nullish-filter-predicate": "error",
|
|
17335
18324
|
"@sarj/prefer-await-in-async-return": "error",
|
|
17336
18325
|
"@sarj/prefer-schema-for-api-payload": "error",
|
|
18326
|
+
"@sarj/prefer-shared-zod-enum": "warn",
|
|
18327
|
+
"@sarj/prefer-switch-for-repeated-equality": "warn",
|
|
17337
18328
|
"@sarj/prefer-semantic-colors": ["error", { requireSemanticTokens: true }],
|
|
17338
18329
|
"@sarj/prefer-server-actions": "error",
|
|
17339
18330
|
"@sarj/prefer-whole-object-assertion": "error",
|
|
@@ -17341,7 +18332,9 @@ var RECOMMENDED_RULES = {
|
|
|
17341
18332
|
"@sarj/prefer-zod-infer": "error",
|
|
17342
18333
|
"@sarj/require-assert-never": "error",
|
|
17343
18334
|
"@sarj/require-fetch-timeout": "error",
|
|
18335
|
+
"@sarj/require-interface-for-exported-class": "warn",
|
|
17344
18336
|
"@sarj/require-port-for-service": "error",
|
|
18337
|
+
"@sarj/require-sql-access-class": "warn",
|
|
17345
18338
|
"@sarj/require-static-next-matcher": "error",
|
|
17346
18339
|
"@sarj/require-use-form-default-values": "error",
|
|
17347
18340
|
"@sarj/require-use-server-in-actions-file": "error",
|
|
@@ -17349,6 +18342,7 @@ var RECOMMENDED_RULES = {
|
|
|
17349
18342
|
"@sarj/store-insert-requires-on-conflict": "error",
|
|
17350
18343
|
"@sarj/stepdown": "error",
|
|
17351
18344
|
"@sarj/source-coupled-test": "error",
|
|
18345
|
+
"@sarj/sole-export-matches-filename": "warn",
|
|
17352
18346
|
"@sarj/test-phase-label-comment": "error",
|
|
17353
18347
|
"@sarj/require-pascal-case-zod-schema-name": "warn"
|
|
17354
18348
|
};
|
|
@@ -17409,10 +18403,15 @@ var STRICT_RULES = {
|
|
|
17409
18403
|
"@sarj/prefer-immutable-module-constant": "error",
|
|
17410
18404
|
"@sarj/prefer-module-level-constant": "error",
|
|
17411
18405
|
"@sarj/prefer-module-level-schema": "error",
|
|
18406
|
+
"@sarj/prefer-named-complex-return-type": "warn",
|
|
18407
|
+
"@sarj/prefer-node-crypto-hash": "warn",
|
|
18408
|
+
"@sarj/prefer-node-fs-promises": "warn",
|
|
17412
18409
|
"@sarj/prefer-non-nullable-collection": "error",
|
|
17413
18410
|
"@sarj/prefer-nullish-filter-predicate": "error",
|
|
17414
18411
|
"@sarj/prefer-await-in-async-return": "error",
|
|
17415
18412
|
"@sarj/prefer-schema-for-api-payload": "error",
|
|
18413
|
+
"@sarj/prefer-shared-zod-enum": "warn",
|
|
18414
|
+
"@sarj/prefer-switch-for-repeated-equality": "warn",
|
|
17416
18415
|
"@sarj/prefer-semantic-colors": ["error", { requireSemanticTokens: true }],
|
|
17417
18416
|
"@sarj/prefer-server-actions": "error",
|
|
17418
18417
|
"@sarj/prefer-whole-object-assertion": "error",
|
|
@@ -17420,7 +18419,9 @@ var STRICT_RULES = {
|
|
|
17420
18419
|
"@sarj/prefer-zod-infer": "error",
|
|
17421
18420
|
"@sarj/require-assert-never": "error",
|
|
17422
18421
|
"@sarj/require-fetch-timeout": "error",
|
|
18422
|
+
"@sarj/require-interface-for-exported-class": "warn",
|
|
17423
18423
|
"@sarj/require-port-for-service": "error",
|
|
18424
|
+
"@sarj/require-sql-access-class": "warn",
|
|
17424
18425
|
"@sarj/require-static-next-matcher": "error",
|
|
17425
18426
|
"@sarj/require-use-form-default-values": "error",
|
|
17426
18427
|
"@sarj/require-use-server-in-actions-file": "error",
|
|
@@ -17428,6 +18429,7 @@ var STRICT_RULES = {
|
|
|
17428
18429
|
"@sarj/store-insert-requires-on-conflict": "error",
|
|
17429
18430
|
"@sarj/stepdown": "error",
|
|
17430
18431
|
"@sarj/source-coupled-test": "error",
|
|
18432
|
+
"@sarj/sole-export-matches-filename": "warn",
|
|
17431
18433
|
"@sarj/test-phase-label-comment": "error",
|
|
17432
18434
|
"@sarj/require-pascal-case-zod-schema-name": "warn"
|
|
17433
18435
|
};
|