@sarj/eslint-plugin 16.5.3 → 16.7.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 +174 -67
- package/dist/index.d.cts +9 -9
- package/dist/index.d.ts +9 -9
- package/dist/index.js +249 -142
- package/package.json +1 -1
package/dist/index.cjs
CHANGED
|
@@ -52,7 +52,7 @@ module.exports = __toCommonJS(src_exports);
|
|
|
52
52
|
// package.json
|
|
53
53
|
var package_default = {
|
|
54
54
|
name: "@sarj/eslint-plugin",
|
|
55
|
-
version: "16.
|
|
55
|
+
version: "16.7.0",
|
|
56
56
|
packageManager: "npm@12.1.0",
|
|
57
57
|
description: "Custom ESLint rules for hypermodern TypeScript / React / Next.js projects",
|
|
58
58
|
type: "module",
|
|
@@ -470,8 +470,9 @@ function commentLineEnd(sourceText, start) {
|
|
|
470
470
|
}
|
|
471
471
|
|
|
472
472
|
// src/rules/require-explicit-contract-implementation.ts
|
|
473
|
+
var ESCAPED_CLASSES = /* @__PURE__ */ new WeakMap();
|
|
473
474
|
var REQUIRE_EXPLICIT_CONTRACT_IMPLEMENTATION_DOCUMENTATION = {
|
|
474
|
-
defaultLevel: "
|
|
475
|
+
defaultLevel: "error",
|
|
475
476
|
summary: "Require nominal inheritance when an injected abstract class is rejected by an instanceof guard.",
|
|
476
477
|
rationale: "A structurally assignable fake can still fail a constructor's nominal runtime guard. Pure structural interfaces do not require an implements clause.",
|
|
477
478
|
remediation: "Use an implementation inheriting the existing abstract class, or remove the nominal guard if the boundary is intentionally structural.",
|
|
@@ -479,8 +480,8 @@ var REQUIRE_EXPLICIT_CONTRACT_IMPLEMENTATION_DOCUMENTATION = {
|
|
|
479
480
|
autofix: "none",
|
|
480
481
|
limitations: [
|
|
481
482
|
"Requires direct construction of both owned consumer and collaborator classes, with a first-statement consumer constructor guard rejecting the exact parameter with if (!(parameter instanceof Contract)) throw.",
|
|
482
|
-
"The contract must resolve to an abstract class without decorators, unresolved ancestors, or custom computed static members in its resolved hierarchy.",
|
|
483
|
-
"Structural interfaces, non-rejecting branches, reassignment before the guard, casts, unresolved heritage, dynamic factories, explicit implementation constructors or initializers, modules referencing prototype-mutator members or assigning prototypes, and third-party classes are excluded."
|
|
483
|
+
"The contract must resolve to an abstract class without decorators, static blocks, unresolved ancestors, or custom computed static members in its resolved hierarchy. Escaped class constructors are checked across every owned module in the typed program.",
|
|
484
|
+
"Structural interfaces, non-rejecting branches, reassignment before the guard, casts, unresolved heritage, dynamic factories, implementation static blocks, explicit implementation constructors or initializers, involved modules referencing prototype-mutator members or assigning prototypes, escaped class constructors, and third-party classes are excluded."
|
|
484
485
|
],
|
|
485
486
|
examples: [
|
|
486
487
|
{
|
|
@@ -503,6 +504,115 @@ var REQUIRE_EXPLICIT_CONTRACT_IMPLEMENTATION_DOCUMENTATION = {
|
|
|
503
504
|
}
|
|
504
505
|
]
|
|
505
506
|
};
|
|
507
|
+
function hasPrototypeMutation(source) {
|
|
508
|
+
function visit(node) {
|
|
509
|
+
const member = memberName(node);
|
|
510
|
+
if (member === "setPrototypeOf" || member === "__proto__" || member === "hasInstance") return true;
|
|
511
|
+
if (ts.isBinaryExpression(node) && node.operatorToken.kind >= ts.SyntaxKind.FirstAssignment && node.operatorToken.kind <= ts.SyntaxKind.LastAssignment && memberName(node.left) === "prototype") return true;
|
|
512
|
+
return ts.forEachChild(node, visit);
|
|
513
|
+
}
|
|
514
|
+
return visit(source) === true;
|
|
515
|
+
}
|
|
516
|
+
function memberName(node) {
|
|
517
|
+
if (ts.isPropertyAccessExpression(node)) return node.name.text;
|
|
518
|
+
if (ts.isElementAccessExpression(node) && ts.isStringLiteralLike(node.argumentExpression)) return node.argumentExpression.text;
|
|
519
|
+
return null;
|
|
520
|
+
}
|
|
521
|
+
function ownedSource(source) {
|
|
522
|
+
return !source.isDeclarationFile && !/(?:^|[/\\])(?:node_modules|vendor|vendored|generated|dist)(?:[/\\])/u.test(source.fileName) && !isGeneratedFile(source.fileName, source.text);
|
|
523
|
+
}
|
|
524
|
+
function escapedClasses(program, checker) {
|
|
525
|
+
const cached = ESCAPED_CLASSES.get(program);
|
|
526
|
+
if (cached !== void 0) return cached;
|
|
527
|
+
const escaped = /* @__PURE__ */ new Set();
|
|
528
|
+
const namespaceValues = /* @__PURE__ */ new Map();
|
|
529
|
+
function visit(node) {
|
|
530
|
+
if (ts.isTypeNode(node) || ts.isImportDeclaration(node)) return;
|
|
531
|
+
if (ts.isIdentifier(node) || ts.isPropertyAccessExpression(node) || ts.isElementAccessExpression(node)) {
|
|
532
|
+
recordEscapedReference(checker, node, escaped, namespaceValues);
|
|
533
|
+
}
|
|
534
|
+
ts.forEachChild(node, visit);
|
|
535
|
+
}
|
|
536
|
+
for (const source of program.getSourceFiles()) if (ownedSource(source)) visit(source);
|
|
537
|
+
ESCAPED_CLASSES.set(program, escaped);
|
|
538
|
+
return escaped;
|
|
539
|
+
}
|
|
540
|
+
function recordEscapedReference(checker, node, escaped, namespaceValues) {
|
|
541
|
+
const symbol = canonicalSymbol(checker, node);
|
|
542
|
+
if (symbol !== void 0) {
|
|
543
|
+
let values = namespaceValues.get(symbol);
|
|
544
|
+
if (values === void 0) {
|
|
545
|
+
values = ownedClassValues(checker, symbol);
|
|
546
|
+
namespaceValues.set(symbol, values);
|
|
547
|
+
}
|
|
548
|
+
if (!namespacePrefix(symbol, node) && !safeClassReference(node)) for (const value of values) escaped.add(value);
|
|
549
|
+
}
|
|
550
|
+
if (ts.isElementAccessExpression(node) && !safeClassReference(node)) {
|
|
551
|
+
const receiver = canonicalSymbol(checker, node.expression) ?? checker.getTypeAtLocation(node.expression).getSymbol();
|
|
552
|
+
if (receiver !== void 0) for (const value of ownedClassValues(checker, receiver)) escaped.add(value);
|
|
553
|
+
}
|
|
554
|
+
}
|
|
555
|
+
function ownedClassValues(checker, original, seen = /* @__PURE__ */ new Set()) {
|
|
556
|
+
const symbol = original.flags & ts.SymbolFlags.Alias ? checker.getAliasedSymbol(original) : original;
|
|
557
|
+
const values = /* @__PURE__ */ new Set();
|
|
558
|
+
if (seen.has(symbol)) return values;
|
|
559
|
+
seen.add(symbol);
|
|
560
|
+
if (symbol.declarations?.some((declaration) => ts.isClassDeclaration(declaration) && ownedSource(declaration.getSourceFile()))) values.add(symbol);
|
|
561
|
+
if (symbol.declarations?.some((declaration) => (ts.isSourceFile(declaration) || ts.isModuleDeclaration(declaration)) && ownedSource(declaration.getSourceFile()))) {
|
|
562
|
+
for (const exported of checker.getExportsOfModule(symbol)) {
|
|
563
|
+
for (const value of ownedClassValues(checker, exported, seen)) values.add(value);
|
|
564
|
+
}
|
|
565
|
+
}
|
|
566
|
+
return values;
|
|
567
|
+
}
|
|
568
|
+
function safeClassReference(node) {
|
|
569
|
+
let reference = ts.isPropertyAccessExpression(node.parent) && node.parent.name === node ? node.parent : node;
|
|
570
|
+
while (ts.isParenthesizedExpression(reference.parent)) reference = reference.parent;
|
|
571
|
+
const parent = reference.parent;
|
|
572
|
+
return ts.isClassDeclaration(parent) && parent.name === reference || ts.isNewExpression(parent) && parent.expression === reference || ts.isExpressionWithTypeArguments(parent) && parent.expression === reference || ts.isBinaryExpression(parent) && parent.operatorToken.kind === ts.SyntaxKind.InstanceOfKeyword && parent.right === reference;
|
|
573
|
+
}
|
|
574
|
+
function namespacePrefix(symbol, node) {
|
|
575
|
+
const parent = node.parent;
|
|
576
|
+
const memberCall = (ts.isPropertyAccessExpression(parent) || ts.isElementAccessExpression(parent)) && ts.isCallExpression(parent.parent) && parent.parent.expression === parent;
|
|
577
|
+
return !symbol.declarations?.some(ts.isClassDeclaration) && (ts.isPropertyAccessExpression(parent) || ts.isElementAccessExpression(parent)) && parent.expression === node && !memberCall;
|
|
578
|
+
}
|
|
579
|
+
function closedNominalBoundary(program, checker, call, consumer, missing) {
|
|
580
|
+
const { implementation, contractSymbol } = missing;
|
|
581
|
+
const implementationSymbol = implementation.name === void 0 ? void 0 : canonicalSymbol(checker, implementation.name);
|
|
582
|
+
const consumerSymbol = consumer.name === void 0 ? void 0 : canonicalSymbol(checker, consumer.name);
|
|
583
|
+
if (implementationSymbol === void 0 || consumerSymbol === void 0) return false;
|
|
584
|
+
const contract = contractSymbol.declarations?.find(ts.isClassDeclaration);
|
|
585
|
+
if (contract === void 0) return false;
|
|
586
|
+
const targets = /* @__PURE__ */ new Set([consumerSymbol, ...classHierarchySymbols(checker, contract), ...classHierarchySymbols(checker, implementation)]);
|
|
587
|
+
const sources = /* @__PURE__ */ new Set([call.getSourceFile(), consumer.getSourceFile(), implementation.getSourceFile(), ...contractSymbol.declarations?.map((item) => item.getSourceFile()) ?? []]);
|
|
588
|
+
return ![...sources].some(hasPrototypeMutation) && ![...targets].some((target) => escapedClasses(program, checker).has(target));
|
|
589
|
+
}
|
|
590
|
+
function classHierarchySymbols(checker, declaration, seen = /* @__PURE__ */ new Set()) {
|
|
591
|
+
const symbol = declaration.name === void 0 ? void 0 : canonicalSymbol(checker, declaration.name);
|
|
592
|
+
if (symbol === void 0 || seen.has(symbol)) return seen;
|
|
593
|
+
seen.add(symbol);
|
|
594
|
+
for (const clause of declaration.heritageClauses ?? []) {
|
|
595
|
+
if (clause.token !== ts.SyntaxKind.ExtendsKeyword) continue;
|
|
596
|
+
for (const parent of clause.types) {
|
|
597
|
+
const ancestor = canonicalSymbol(checker, parent.expression)?.declarations?.find(ts.isClassDeclaration);
|
|
598
|
+
if (ancestor !== void 0) classHierarchySymbols(checker, ancestor, seen);
|
|
599
|
+
}
|
|
600
|
+
}
|
|
601
|
+
return seen;
|
|
602
|
+
}
|
|
603
|
+
function missingImplementation(checker, signature, parameter, call, argument) {
|
|
604
|
+
const parameterType = checker.getTypeOfSymbolAtLocation(parameter, call);
|
|
605
|
+
const contractType = behavioralContract(checker, parameterType);
|
|
606
|
+
if (contractType === null) return null;
|
|
607
|
+
const contractSymbol = contractType.getSymbol();
|
|
608
|
+
if (contractSymbol === void 0 || !hasNominalRejectionGuard(checker, signature, parameter, contractSymbol)) return null;
|
|
609
|
+
const actualType = checker.getTypeAtLocation(argument);
|
|
610
|
+
if (!checker.isTypeAssignableTo(actualType, contractType)) return null;
|
|
611
|
+
const implementation = ownedClass(checker, argument);
|
|
612
|
+
if (implementation === null) return null;
|
|
613
|
+
if (nominallyInherits(checker, implementation, contractSymbol, /* @__PURE__ */ new Set()) !== false) return null;
|
|
614
|
+
return { implementation, contractSymbol };
|
|
615
|
+
}
|
|
506
616
|
function behavioralContract(checker, type) {
|
|
507
617
|
if (type.isUnion()) {
|
|
508
618
|
const substantive = type.types.filter((member) => (member.flags & (ts.TypeFlags.Null | ts.TypeFlags.Undefined)) === 0);
|
|
@@ -527,23 +637,9 @@ function ownedClass(checker, expression) {
|
|
|
527
637
|
if (declaration === void 0 || declaration !== constructed || declaration.getSourceFile().isDeclarationFile || /(?:^|[/\\])(?:node_modules|vendor|generated)(?:[/\\])/u.test(declaration.getSourceFile().fileName)) return null;
|
|
528
638
|
return declaration;
|
|
529
639
|
}
|
|
530
|
-
function memberName(node) {
|
|
531
|
-
if (ts.isPropertyAccessExpression(node)) return node.name.text;
|
|
532
|
-
if (ts.isElementAccessExpression(node) && ts.isStringLiteralLike(node.argumentExpression)) return node.argumentExpression.text;
|
|
533
|
-
return null;
|
|
534
|
-
}
|
|
535
|
-
function hasPrototypeMutation(source) {
|
|
536
|
-
function visit(node) {
|
|
537
|
-
const member = memberName(node);
|
|
538
|
-
if (member === "setPrototypeOf" || member === "__proto__" || member === "hasInstance") return true;
|
|
539
|
-
if (ts.isBinaryExpression(node) && node.operatorToken.kind >= ts.SyntaxKind.FirstAssignment && node.operatorToken.kind <= ts.SyntaxKind.LastAssignment && memberName(node.left) === "prototype") return true;
|
|
540
|
-
return ts.forEachChild(node, visit);
|
|
541
|
-
}
|
|
542
|
-
return visit(source) === true;
|
|
543
|
-
}
|
|
544
640
|
function nominallyInherits(checker, declaration, target, seen) {
|
|
545
641
|
if (ts.canHaveDecorators(declaration) && ts.getDecorators(declaration)?.length) return null;
|
|
546
|
-
if (hasPrototypeMutation(declaration.getSourceFile()) || declaration.members.some((member) => ts.isConstructorDeclaration(member) || ts.isPropertyDeclaration(member) && member.initializer !== void 0)) return null;
|
|
642
|
+
if (hasPrototypeMutation(declaration.getSourceFile()) || declaration.members.some((member) => ts.isConstructorDeclaration(member) || ts.isClassStaticBlockDeclaration(member) || ts.isPropertyDeclaration(member) && member.initializer !== void 0)) return null;
|
|
547
643
|
const symbol = declaration.name === void 0 ? void 0 : canonicalSymbol(checker, declaration.name);
|
|
548
644
|
if (symbol !== void 0) {
|
|
549
645
|
if (seen.has(symbol)) return null;
|
|
@@ -558,10 +654,6 @@ function nominallyInherits(checker, declaration, target, seen) {
|
|
|
558
654
|
const inherited = parentSymbol.declarations?.find(ts.isClassDeclaration);
|
|
559
655
|
return inherited === void 0 ? null : nominallyInherits(checker, inherited, target, new Set(seen));
|
|
560
656
|
}
|
|
561
|
-
function canonicalSymbol(checker, node) {
|
|
562
|
-
const symbol = checker.getSymbolAtLocation(node);
|
|
563
|
-
return symbol === void 0 ? void 0 : (symbol.flags & ts.SymbolFlags.Alias) !== 0 ? checker.getAliasedSymbol(symbol) : symbol;
|
|
564
|
-
}
|
|
565
657
|
function hasNominalRejectionGuard(checker, signature, parameter, contract) {
|
|
566
658
|
const declaration = signature.getDeclaration();
|
|
567
659
|
if (declaration === void 0 || !ts.isConstructorDeclaration(declaration)) return false;
|
|
@@ -586,7 +678,7 @@ function alwaysThrows(statement) {
|
|
|
586
678
|
return ts.isThrowStatement(statement) || ts.isBlock(statement) && statement.statements.length === 1 && ts.isThrowStatement(statement.statements[0]);
|
|
587
679
|
}
|
|
588
680
|
function hasOrdinaryInstanceCheck(checker, declaration, seen) {
|
|
589
|
-
if (seen.has(declaration) || ts.getDecorators(declaration)?.length || hasPrototypeMutation(declaration.getSourceFile())) return false;
|
|
681
|
+
if (seen.has(declaration) || ts.getDecorators(declaration)?.length || hasPrototypeMutation(declaration.getSourceFile()) || declaration.members.some(ts.isClassStaticBlockDeclaration)) return false;
|
|
590
682
|
seen.add(declaration);
|
|
591
683
|
if (declaration.members.some((member) => member.name !== void 0 && ts.isComputedPropertyName(member.name) && ts.canHaveModifiers(member) && ts.getModifiers(member)?.some((modifier) => modifier.kind === ts.SyntaxKind.StaticKeyword))) return false;
|
|
592
684
|
for (const clause of declaration.heritageClauses ?? []) {
|
|
@@ -598,6 +690,10 @@ function hasOrdinaryInstanceCheck(checker, declaration, seen) {
|
|
|
598
690
|
}
|
|
599
691
|
return true;
|
|
600
692
|
}
|
|
693
|
+
function canonicalSymbol(checker, node) {
|
|
694
|
+
const symbol = checker.getSymbolAtLocation(node);
|
|
695
|
+
return symbol === void 0 ? void 0 : (symbol.flags & ts.SymbolFlags.Alias) !== 0 ? checker.getAliasedSymbol(symbol) : symbol;
|
|
696
|
+
}
|
|
601
697
|
var require_explicit_contract_implementation_default = createRule({
|
|
602
698
|
name: "require-explicit-contract-implementation",
|
|
603
699
|
documentation: REQUIRE_EXPLICIT_CONTRACT_IMPLEMENTATION_DOCUMENTATION,
|
|
@@ -627,22 +723,13 @@ var require_explicit_contract_implementation_default = createRule({
|
|
|
627
723
|
if (argument.type !== import_utils2.AST_NODE_TYPES.NewExpression) continue;
|
|
628
724
|
const parameter = parameters[index];
|
|
629
725
|
if (parameter === void 0) continue;
|
|
630
|
-
const parameterType = checker.getTypeOfSymbolAtLocation(parameter, tsNode);
|
|
631
|
-
const contractType = behavioralContract(checker, parameterType);
|
|
632
|
-
if (contractType === null) continue;
|
|
633
|
-
const contractSymbol = contractType.getSymbol();
|
|
634
|
-
if (contractSymbol === void 0 || !hasNominalRejectionGuard(checker, signature, parameter, contractSymbol)) continue;
|
|
635
726
|
const tsArgument = services.esTreeNodeToTSNodeMap.get(argument);
|
|
636
|
-
const
|
|
637
|
-
if (!
|
|
638
|
-
const implementation = ownedClass(checker, tsArgument);
|
|
639
|
-
if (implementation === null) continue;
|
|
640
|
-
const relationship = nominallyInherits(checker, implementation, contractSymbol, /* @__PURE__ */ new Set());
|
|
641
|
-
if (relationship !== false) continue;
|
|
727
|
+
const missing = missingImplementation(checker, signature, parameter, tsNode, tsArgument);
|
|
728
|
+
if (missing === null || !closedNominalBoundary(services.program, checker, tsNode, consumer, missing)) continue;
|
|
642
729
|
context.report({
|
|
643
730
|
node: argument,
|
|
644
731
|
messageId: "declareActualContract",
|
|
645
|
-
data: { implementation: implementation.name?.text ?? "class", contract: contractSymbol.getName() }
|
|
732
|
+
data: { implementation: missing.implementation.name?.text ?? "class", contract: missing.contractSymbol.getName() }
|
|
646
733
|
});
|
|
647
734
|
}
|
|
648
735
|
}
|
|
@@ -7618,7 +7705,8 @@ var NO_IMPOSSIBLE_ZOD_LITERAL_BOUNDS_DOCUMENTATION = {
|
|
|
7618
7705
|
remediation: "Choose compatible lower and upper bounds, or remove the constraint that does not express the intended domain.",
|
|
7619
7706
|
category: "correctness",
|
|
7620
7707
|
limitations: [
|
|
7621
|
-
"Only finite numeric literals in a single number, string, or array schema chain are compared.",
|
|
7708
|
+
"Only finite numeric literals in a single number, string, or array schema chain are compared; explicit int() chains also require an admitted integer.",
|
|
7709
|
+
"Integer-domain comparisons abstain near the JavaScript safe-integer boundary.",
|
|
7622
7710
|
"Chains with dynamic bounds, non-bound validators, transforms, pipes, or preprocessors are skipped.",
|
|
7623
7711
|
"Test and generated files are excluded."
|
|
7624
7712
|
],
|
|
@@ -7657,6 +7745,7 @@ var KINDS = /* @__PURE__ */ new Set(["array", "number", "string"]);
|
|
|
7657
7745
|
var NUMBER_METHODS = /* @__PURE__ */ new Set([
|
|
7658
7746
|
"gt",
|
|
7659
7747
|
"gte",
|
|
7748
|
+
"int",
|
|
7660
7749
|
"lt",
|
|
7661
7750
|
"lte",
|
|
7662
7751
|
"max",
|
|
@@ -7698,9 +7787,20 @@ function strongerUpper(current, candidate2) {
|
|
|
7698
7787
|
}
|
|
7699
7788
|
return current;
|
|
7700
7789
|
}
|
|
7701
|
-
function isEmpty(lower, upper) {
|
|
7790
|
+
function isEmpty(lower, upper, integer) {
|
|
7702
7791
|
if (lower === null || upper === null) return false;
|
|
7703
|
-
|
|
7792
|
+
const realEmpty = lower.value > upper.value || lower.value === upper.value && (lower.exclusive || upper.exclusive);
|
|
7793
|
+
if (integer) {
|
|
7794
|
+
if (realEmpty) return false;
|
|
7795
|
+
const safeMargin = Number.MAX_SAFE_INTEGER - 1;
|
|
7796
|
+
if (Math.abs(lower.value) >= safeMargin || Math.abs(upper.value) >= safeMargin) {
|
|
7797
|
+
return false;
|
|
7798
|
+
}
|
|
7799
|
+
const minimum = lower.exclusive ? Math.floor(lower.value) + 1 : Math.ceil(lower.value);
|
|
7800
|
+
const maximum = upper.exclusive ? Math.ceil(upper.value) - 1 : Math.floor(upper.value);
|
|
7801
|
+
return minimum > maximum;
|
|
7802
|
+
}
|
|
7803
|
+
return realEmpty;
|
|
7704
7804
|
}
|
|
7705
7805
|
function isOutermostCall(node) {
|
|
7706
7806
|
const parent = node.parent;
|
|
@@ -7794,6 +7894,7 @@ var no_impossible_zod_literal_bounds_default = createRule({
|
|
|
7794
7894
|
const allowed = chain.kind === "number" ? NUMBER_METHODS : LENGTH_METHODS;
|
|
7795
7895
|
let lower = null;
|
|
7796
7896
|
let upper = null;
|
|
7897
|
+
let integer = false;
|
|
7797
7898
|
function addBound(method, semantic, value) {
|
|
7798
7899
|
const label = `${method}(${String(value)})`;
|
|
7799
7900
|
if (semantic !== null) {
|
|
@@ -7829,6 +7930,11 @@ var no_impossible_zod_literal_bounds_default = createRule({
|
|
|
7829
7930
|
}
|
|
7830
7931
|
for (const { method, node } of chain.calls) {
|
|
7831
7932
|
if (!allowed.has(method)) return null;
|
|
7933
|
+
if (method === "int") {
|
|
7934
|
+
if (node.arguments.length !== 0) return null;
|
|
7935
|
+
integer = true;
|
|
7936
|
+
continue;
|
|
7937
|
+
}
|
|
7832
7938
|
const semantic = zeroBoundSemantic(method);
|
|
7833
7939
|
const value = semantic?.value ?? finiteNumber(node.arguments[0]);
|
|
7834
7940
|
if (value === null) return null;
|
|
@@ -7838,7 +7944,7 @@ var no_impossible_zod_literal_bounds_default = createRule({
|
|
|
7838
7944
|
if (semantic !== null && node.arguments.length !== 0) return null;
|
|
7839
7945
|
addBound(method, semantic, value);
|
|
7840
7946
|
}
|
|
7841
|
-
return isEmpty(lower, upper) && lower !== null && upper !== null ? { lower, upper } : null;
|
|
7947
|
+
return isEmpty(lower, upper, integer) && lower !== null && upper !== null ? { lower, upper } : null;
|
|
7842
7948
|
}
|
|
7843
7949
|
return {
|
|
7844
7950
|
ImportDeclaration(node) {
|
|
@@ -17695,14 +17801,14 @@ var prefer_named_callback_domain_default = createRule({
|
|
|
17695
17801
|
// src/rules/prefer-named-complex-return-type.ts
|
|
17696
17802
|
var import_utils101 = require("@typescript-eslint/utils");
|
|
17697
17803
|
var PREFER_NAMED_COMPLEX_RETURN_TYPE_DOCUMENTATION = {
|
|
17698
|
-
defaultLevel: "
|
|
17804
|
+
defaultLevel: "error",
|
|
17699
17805
|
summary: "Prefer a named contract for structurally complex function return types.",
|
|
17700
17806
|
rationale: "A large inline return annotation hides a reusable domain concept and makes signatures difficult to scan.",
|
|
17701
17807
|
remediation: "Name the complex nested shape while preserving its generic wrappers and type parameters; reference the named contract from the return annotation.",
|
|
17702
17808
|
category: "maintainability",
|
|
17703
17809
|
limitations: [
|
|
17704
17810
|
"Only explicit object types with at least three members and unions with at least three object variants are reported.",
|
|
17705
|
-
"Any single-argument generic wrapper is traversed to find nested shapes, not assumed semantically transparent. Inferred return types are outside this rule; extraction is manual and must preserve locally bound type parameters."
|
|
17811
|
+
"Any single-argument generic wrapper is traversed to find nested shapes, not assumed semantically transparent. Inferred return types are outside this rule; extraction is manual and must preserve locally bound type parameters with generic named contracts. Types depending on polymorphic this or a local value query are excluded."
|
|
17706
17812
|
],
|
|
17707
17813
|
examples: [
|
|
17708
17814
|
{ 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 },
|
|
@@ -17718,10 +17824,13 @@ function unwrap4(node) {
|
|
|
17718
17824
|
}
|
|
17719
17825
|
function report(context, node) {
|
|
17720
17826
|
const annotation = node.returnType?.typeAnnotation;
|
|
17721
|
-
if (annotation !== void 0 && isComplex(annotation)) {
|
|
17827
|
+
if (annotation !== void 0 && isComplex(annotation) && !hasValueDependency(annotation)) {
|
|
17722
17828
|
context.report({ node: annotation, messageId: "nameComplexReturnType" });
|
|
17723
17829
|
}
|
|
17724
17830
|
}
|
|
17831
|
+
function hasValueDependency(node) {
|
|
17832
|
+
return node.type === import_utils101.AST_NODE_TYPES.TSThisType || node.type === import_utils101.AST_NODE_TYPES.TSTypeQuery || forEachOwnAstChild(node, hasValueDependency);
|
|
17833
|
+
}
|
|
17725
17834
|
function isComplex(node) {
|
|
17726
17835
|
const type = unwrap4(node);
|
|
17727
17836
|
if (type.type === import_utils101.AST_NODE_TYPES.TSTypeLiteral) return type.members.length >= 3;
|
|
@@ -19369,20 +19478,20 @@ var prefer_shared_zod_enum_default = createRule({
|
|
|
19369
19478
|
// src/rules/prefer-switch-for-repeated-equality.ts
|
|
19370
19479
|
var import_utils110 = require("@typescript-eslint/utils");
|
|
19371
19480
|
var PREFER_SWITCH_FOR_REPEATED_EQUALITY_DOCUMENTATION = {
|
|
19372
|
-
defaultLevel: "
|
|
19481
|
+
defaultLevel: "error",
|
|
19373
19482
|
summary: "Prefer switch over long if/else-if chains that compare one value for strict equality.",
|
|
19374
19483
|
rationale: "A switch makes finite dispatch cases visually uniform and easier to extend without duplicating the discriminant.",
|
|
19375
19484
|
remediation: "Replace three or more strict-equality branches over the same discriminant with a switch; keep if statements for ranges, guards, and heterogeneous predicates.",
|
|
19376
19485
|
category: "maintainability",
|
|
19377
19486
|
limitations: [
|
|
19378
19487
|
"Only direct if/else-if chains with at least three strict-equality tests are reported.",
|
|
19379
|
-
"The discriminant must be a
|
|
19380
|
-
"Case values
|
|
19488
|
+
"The discriminant must be a resolved lexical variable or parameter; unresolved globals, calls, getters, and indexed reads are excluded. Preserve branch scopes and break/continue targets when converting manually; no autofix is offered.",
|
|
19489
|
+
"Case values must be primitive literals. Member references and named constants are excluded because evaluating them can observe getters or mutate the selector. Generated sources are excluded.",
|
|
19381
19490
|
"The rule deliberately ignores compound predicates, loose equality, ranges, and chains that compare different discriminants."
|
|
19382
19491
|
],
|
|
19383
19492
|
examples: [
|
|
19384
19493
|
{ 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 },
|
|
19385
|
-
{ 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 },
|
|
19494
|
+
{ id: "repeated-equality", title: "Avoid repeating the discriminant", outcome: "match", files: [{ path: "src/render.ts", source: "function render(kind: string) { 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 },
|
|
19386
19495
|
{ id: "escaped-middle", scenarioId: "native-discriminant", title: "Use native identifier identity", outcome: "match", files: [{ path: "src/dispatch.ts", source: `function probe(kind){if(kind==='a')return 1;else if(\\u006bind==='b')return 2;else if(kind==='c')return 3;return 0;}
|
|
19387
19496
|
console.log(JSON.stringify(["a","b","c","d"].map(probe)));` }], focusPath: "src/dispatch.ts", expectedCount: 1, public: true },
|
|
19388
19497
|
{ id: "different-discriminants", scenarioId: "native-discriminant", title: "Use native identifier identity", outcome: "no-match", files: [{ path: "src/dispatch.ts", source: `function probe(kind){const other="other";if(kind==='a')return 1;else if(other==='b')return 2;else if(kind==='c')return 3;return 0;}
|
|
@@ -19398,10 +19507,7 @@ function discriminantName(test) {
|
|
|
19398
19507
|
return discriminant.type === import_utils110.AST_NODE_TYPES.Identifier ? discriminant.name : null;
|
|
19399
19508
|
}
|
|
19400
19509
|
function isCaseValue(node) {
|
|
19401
|
-
|
|
19402
|
-
if (node.type === import_utils110.AST_NODE_TYPES.Identifier) return /^[A-Z][A-Z0-9_]*$/u.test(node.name);
|
|
19403
|
-
if (node.type !== import_utils110.AST_NODE_TYPES.MemberExpression || node.computed) return false;
|
|
19404
|
-
return node.property.type === import_utils110.AST_NODE_TYPES.Identifier && (node.object.type === import_utils110.AST_NODE_TYPES.Identifier || isCaseValue(node.object));
|
|
19510
|
+
return node.type === import_utils110.AST_NODE_TYPES.Literal && !("regex" in node);
|
|
19405
19511
|
}
|
|
19406
19512
|
var prefer_switch_for_repeated_equality_default = createRule({
|
|
19407
19513
|
name: "prefer-switch-for-repeated-equality",
|
|
@@ -19416,11 +19522,16 @@ var prefer_switch_for_repeated_equality_default = createRule({
|
|
|
19416
19522
|
},
|
|
19417
19523
|
defaultOptions: [],
|
|
19418
19524
|
create(context) {
|
|
19525
|
+
if (isGeneratedFile(context.filename, context.sourceCode.text)) return {};
|
|
19419
19526
|
return {
|
|
19420
19527
|
IfStatement(node) {
|
|
19421
19528
|
if (node.parent.type === import_utils110.AST_NODE_TYPES.IfStatement && node.parent.alternate === node) return;
|
|
19422
19529
|
const first = discriminantName(node.test);
|
|
19423
19530
|
if (first === null) return;
|
|
19531
|
+
const binding = import_utils110.ASTUtils.findVariable(context.sourceCode.getScope(node), first);
|
|
19532
|
+
if (binding === null || binding.defs.length !== 1 || binding.scope.type === "global") return;
|
|
19533
|
+
const [definition] = binding.defs;
|
|
19534
|
+
if (definition?.type !== "Parameter" && definition?.type !== "Variable") return;
|
|
19424
19535
|
let count = 1;
|
|
19425
19536
|
let current = node.alternate;
|
|
19426
19537
|
while (current?.type === import_utils110.AST_NODE_TYPES.IfStatement) {
|
|
@@ -21427,17 +21538,17 @@ var UNRESOLVED_TYPE_NODES = /* @__PURE__ */ new Set([
|
|
|
21427
21538
|
import_utils116.AST_NODE_TYPES.TSUnknownKeyword
|
|
21428
21539
|
]);
|
|
21429
21540
|
var NAMED_CHILD_SCHEMA_TYPE_DOCUMENTATION = {
|
|
21430
|
-
defaultLevel: "
|
|
21541
|
+
defaultLevel: "error",
|
|
21431
21542
|
summary: "Reference a named Zod record child's complete schema type instead of repeating its explicit annotation.",
|
|
21432
21543
|
rationale: "Repeating a child schema's generic contract creates a second maintained declaration even though the record already uses that child at runtime.",
|
|
21433
|
-
remediation: "Replace only the matching record type argument with `typeof ChildSchema
|
|
21544
|
+
remediation: "Replace only the matching record type argument with `typeof ChildSchema`, or share one explicit named schema type alias between child and record to retain an independently named public contract. Keep the outer annotation required by isolatedDeclarations and every runtime schema operation.",
|
|
21434
21545
|
category: "maintainability",
|
|
21435
21546
|
autofix: "none",
|
|
21436
21547
|
limitations: [
|
|
21437
21548
|
"Only direct module-level const z.record calls with two arguments, a ZodRecord annotation, and an earlier local const child with a complete explicit Zod type are inspected.",
|
|
21438
21549
|
"The entire generic child annotation must match token for token; input/output, defaults, transforms, readonly modifiers and brands are never compared by output shape alone.",
|
|
21439
21550
|
"Bare leaf types, broad ZodType constraints, type queries, imported or unqualified type references, annotation cycles, comments on the repeated argument, mutable bindings and generated files are excluded.",
|
|
21440
|
-
"Import aliases and namespace imports resolve through scope bindings. Independent public contract pins
|
|
21551
|
+
"Import aliases and namespace imports resolve through scope bindings. Independent public contract pins can use one shared named type alias or an exact reasoned suppression; runtime validation and outer annotations are preserved."
|
|
21441
21552
|
],
|
|
21442
21553
|
examples: [
|
|
21443
21554
|
{ id: "named-child", title: "Reference the named child contract", outcome: "no-match", files: [{ path: "src/record.ts", source: 'import { z } from "zod"; const KeySchema: z.ZodEnum<{ a: "a"; b: "b" }> = z.enum(["a", "b"]); export const RecordSchema: z.ZodRecord<typeof KeySchema, z.ZodString> = z.record(KeySchema, z.string());' }], focusPath: "src/record.ts", expectedCount: 0, public: true },
|
|
@@ -21456,7 +21567,7 @@ var named_child_schema_type_default = createRule({
|
|
|
21456
21567
|
type: "suggestion",
|
|
21457
21568
|
docs: { description: NAMED_CHILD_SCHEMA_TYPE_DOCUMENTATION.summary },
|
|
21458
21569
|
schema: [],
|
|
21459
|
-
messages: { namedChildType: "Use `typeof {{name}}` for this exact child contract; keep the outer schema annotation and runtime operations." }
|
|
21570
|
+
messages: { namedChildType: "Use `typeof {{name}}` or one shared named type alias for this exact child contract; keep the outer schema annotation and runtime operations." }
|
|
21460
21571
|
},
|
|
21461
21572
|
defaultOptions: [],
|
|
21462
21573
|
create(context) {
|
|
@@ -24856,7 +24967,6 @@ var LIBRARY_IMPORT_POLICY = ["error", {
|
|
|
24856
24967
|
}];
|
|
24857
24968
|
var ADVISORY_RULES = [
|
|
24858
24969
|
"@sarj/excessive-commentary",
|
|
24859
|
-
"@sarj/named-child-schema-type",
|
|
24860
24970
|
"@sarj/no-bespoke-api-case-conversion",
|
|
24861
24971
|
"@sarj/no-duplicate-test-case",
|
|
24862
24972
|
"@sarj/no-json-stringify-object-equality",
|
|
@@ -24865,21 +24975,18 @@ var ADVISORY_RULES = [
|
|
|
24865
24975
|
"@sarj/prefer-millisecond-control-duration-schema",
|
|
24866
24976
|
"@sarj/prefer-module-level-refined-schema",
|
|
24867
24977
|
"@sarj/prefer-multi-value-zod-literal",
|
|
24868
|
-
"@sarj/prefer-named-complex-return-type",
|
|
24869
24978
|
"@sarj/prefer-node-crypto-hash",
|
|
24870
24979
|
"@sarj/prefer-node-fs-promises",
|
|
24871
24980
|
"@sarj/prefer-nominal-id-types",
|
|
24872
24981
|
"@sarj/prefer-shared-zod-enum",
|
|
24873
|
-
"@sarj/prefer-switch-for-repeated-equality",
|
|
24874
24982
|
"@sarj/prefer-whole-object-assertion",
|
|
24875
24983
|
"@sarj/require-camelcase-properties",
|
|
24876
|
-
"@sarj/require-explicit-contract-implementation",
|
|
24877
24984
|
"@sarj/require-explicit-service-contract",
|
|
24878
24985
|
"@sarj/require-interface-for-exported-class",
|
|
24879
24986
|
"@sarj/require-sql-access-class"
|
|
24880
24987
|
];
|
|
24881
24988
|
var RECOMMENDED_RULES = {
|
|
24882
|
-
"@sarj/named-child-schema-type": "
|
|
24989
|
+
"@sarj/named-child-schema-type": "error",
|
|
24883
24990
|
"@sarj/no-conditional-empty-object-spread": "error",
|
|
24884
24991
|
"@sarj/prefer-typed-reflection": "error",
|
|
24885
24992
|
"@sarj/no-broad-return-type": "error",
|
|
@@ -24963,7 +25070,7 @@ var RECOMMENDED_RULES = {
|
|
|
24963
25070
|
"@sarj/prefer-multi-value-zod-literal": ["warn", { zodMajorVersion: 4 }],
|
|
24964
25071
|
"@sarj/prefer-named-callback-domain": "error",
|
|
24965
25072
|
"@sarj/prefer-nominal-id-types": "warn",
|
|
24966
|
-
"@sarj/prefer-named-complex-return-type": "
|
|
25073
|
+
"@sarj/prefer-named-complex-return-type": "error",
|
|
24967
25074
|
"@sarj/prefer-node-crypto-hash": "warn",
|
|
24968
25075
|
"@sarj/prefer-node-fs-promises": "warn",
|
|
24969
25076
|
"@sarj/prefer-non-nullable-collection": "error",
|
|
@@ -24971,7 +25078,7 @@ var RECOMMENDED_RULES = {
|
|
|
24971
25078
|
"@sarj/prefer-await-in-async-return": "error",
|
|
24972
25079
|
"@sarj/prefer-schema-for-api-payload": "error",
|
|
24973
25080
|
"@sarj/prefer-shared-zod-enum": "warn",
|
|
24974
|
-
"@sarj/prefer-switch-for-repeated-equality": "
|
|
25081
|
+
"@sarj/prefer-switch-for-repeated-equality": "error",
|
|
24975
25082
|
"@sarj/prefer-semantic-colors": ["error", { requireSemanticTokens: true }],
|
|
24976
25083
|
"@sarj/prefer-server-actions": "error",
|
|
24977
25084
|
"@sarj/prefer-whole-object-assertion": "warn",
|
|
@@ -24980,7 +25087,7 @@ var RECOMMENDED_RULES = {
|
|
|
24980
25087
|
"@sarj/prefer-zod-parse-output-type": "error",
|
|
24981
25088
|
"@sarj/require-assert-never": "error",
|
|
24982
25089
|
"@sarj/require-fetch-timeout": "error",
|
|
24983
|
-
"@sarj/require-explicit-contract-implementation": "
|
|
25090
|
+
"@sarj/require-explicit-contract-implementation": "error",
|
|
24984
25091
|
"@sarj/require-explicit-service-contract": "warn",
|
|
24985
25092
|
"@sarj/require-interface-for-exported-class": "warn",
|
|
24986
25093
|
"@sarj/require-port-for-service": "error",
|
|
@@ -24997,7 +25104,7 @@ var RECOMMENDED_RULES = {
|
|
|
24997
25104
|
"@sarj/require-pascal-case-zod-schema-name": "error"
|
|
24998
25105
|
};
|
|
24999
25106
|
var STRICT_RULES = {
|
|
25000
|
-
"@sarj/named-child-schema-type": "
|
|
25107
|
+
"@sarj/named-child-schema-type": "error",
|
|
25001
25108
|
"@sarj/no-conditional-empty-object-spread": "error",
|
|
25002
25109
|
"@sarj/prefer-typed-reflection": "error",
|
|
25003
25110
|
"@sarj/no-broad-return-type": "error",
|
|
@@ -25085,7 +25192,7 @@ var STRICT_RULES = {
|
|
|
25085
25192
|
"@sarj/prefer-multi-value-zod-literal": ["warn", { zodMajorVersion: 4 }],
|
|
25086
25193
|
"@sarj/prefer-named-callback-domain": "error",
|
|
25087
25194
|
"@sarj/prefer-nominal-id-types": "warn",
|
|
25088
|
-
"@sarj/prefer-named-complex-return-type": "
|
|
25195
|
+
"@sarj/prefer-named-complex-return-type": "error",
|
|
25089
25196
|
"@sarj/prefer-node-crypto-hash": "warn",
|
|
25090
25197
|
"@sarj/prefer-node-fs-promises": "warn",
|
|
25091
25198
|
"@sarj/prefer-non-nullable-collection": "error",
|
|
@@ -25093,7 +25200,7 @@ var STRICT_RULES = {
|
|
|
25093
25200
|
"@sarj/prefer-await-in-async-return": "error",
|
|
25094
25201
|
"@sarj/prefer-schema-for-api-payload": "error",
|
|
25095
25202
|
"@sarj/prefer-shared-zod-enum": "warn",
|
|
25096
|
-
"@sarj/prefer-switch-for-repeated-equality": "
|
|
25203
|
+
"@sarj/prefer-switch-for-repeated-equality": "error",
|
|
25097
25204
|
"@sarj/prefer-semantic-colors": ["error", { requireSemanticTokens: true }],
|
|
25098
25205
|
"@sarj/prefer-server-actions": "error",
|
|
25099
25206
|
"@sarj/prefer-whole-object-assertion": "warn",
|
|
@@ -25102,7 +25209,7 @@ var STRICT_RULES = {
|
|
|
25102
25209
|
"@sarj/prefer-zod-parse-output-type": "error",
|
|
25103
25210
|
"@sarj/require-assert-never": "error",
|
|
25104
25211
|
"@sarj/require-fetch-timeout": "error",
|
|
25105
|
-
"@sarj/require-explicit-contract-implementation": "
|
|
25212
|
+
"@sarj/require-explicit-contract-implementation": "error",
|
|
25106
25213
|
"@sarj/require-explicit-service-contract": "warn",
|
|
25107
25214
|
"@sarj/require-interface-for-exported-class": "warn",
|
|
25108
25215
|
"@sarj/require-port-for-service": "error",
|
package/dist/index.d.cts
CHANGED
|
@@ -291,9 +291,9 @@ declare const RULES: {
|
|
|
291
291
|
/** @deprecated All repositories use one policy; retained for import compatibility. */
|
|
292
292
|
declare const APPLICATION_ONLY_RULES: readonly [];
|
|
293
293
|
/** Rules staged as non-blocking warnings while corpus adoption evidence accumulates. */
|
|
294
|
-
declare const ADVISORY_RULES: readonly ["@sarj/excessive-commentary", "@sarj/
|
|
294
|
+
declare const ADVISORY_RULES: readonly ["@sarj/excessive-commentary", "@sarj/no-bespoke-api-case-conversion", "@sarj/no-duplicate-test-case", "@sarj/no-json-stringify-object-equality", "@sarj/no-restated-comment", "@sarj/no-restated-jsdoc", "@sarj/prefer-millisecond-control-duration-schema", "@sarj/prefer-module-level-refined-schema", "@sarj/prefer-multi-value-zod-literal", "@sarj/prefer-node-crypto-hash", "@sarj/prefer-node-fs-promises", "@sarj/prefer-nominal-id-types", "@sarj/prefer-shared-zod-enum", "@sarj/prefer-whole-object-assertion", "@sarj/require-camelcase-properties", "@sarj/require-explicit-service-contract", "@sarj/require-interface-for-exported-class", "@sarj/require-sql-access-class"];
|
|
295
295
|
declare const RECOMMENDED_RULES: {
|
|
296
|
-
readonly "@sarj/named-child-schema-type": "
|
|
296
|
+
readonly "@sarj/named-child-schema-type": "error";
|
|
297
297
|
readonly "@sarj/no-conditional-empty-object-spread": "error";
|
|
298
298
|
readonly "@sarj/prefer-typed-reflection": "error";
|
|
299
299
|
readonly "@sarj/no-broad-return-type": "error";
|
|
@@ -570,7 +570,7 @@ declare const RECOMMENDED_RULES: {
|
|
|
570
570
|
}];
|
|
571
571
|
readonly "@sarj/prefer-named-callback-domain": "error";
|
|
572
572
|
readonly "@sarj/prefer-nominal-id-types": "warn";
|
|
573
|
-
readonly "@sarj/prefer-named-complex-return-type": "
|
|
573
|
+
readonly "@sarj/prefer-named-complex-return-type": "error";
|
|
574
574
|
readonly "@sarj/prefer-node-crypto-hash": "warn";
|
|
575
575
|
readonly "@sarj/prefer-node-fs-promises": "warn";
|
|
576
576
|
readonly "@sarj/prefer-non-nullable-collection": "error";
|
|
@@ -578,7 +578,7 @@ declare const RECOMMENDED_RULES: {
|
|
|
578
578
|
readonly "@sarj/prefer-await-in-async-return": "error";
|
|
579
579
|
readonly "@sarj/prefer-schema-for-api-payload": "error";
|
|
580
580
|
readonly "@sarj/prefer-shared-zod-enum": "warn";
|
|
581
|
-
readonly "@sarj/prefer-switch-for-repeated-equality": "
|
|
581
|
+
readonly "@sarj/prefer-switch-for-repeated-equality": "error";
|
|
582
582
|
readonly "@sarj/prefer-semantic-colors": readonly ["error", {
|
|
583
583
|
readonly requireSemanticTokens: true;
|
|
584
584
|
}];
|
|
@@ -589,7 +589,7 @@ declare const RECOMMENDED_RULES: {
|
|
|
589
589
|
readonly "@sarj/prefer-zod-parse-output-type": "error";
|
|
590
590
|
readonly "@sarj/require-assert-never": "error";
|
|
591
591
|
readonly "@sarj/require-fetch-timeout": "error";
|
|
592
|
-
readonly "@sarj/require-explicit-contract-implementation": "
|
|
592
|
+
readonly "@sarj/require-explicit-contract-implementation": "error";
|
|
593
593
|
readonly "@sarj/require-explicit-service-contract": "warn";
|
|
594
594
|
readonly "@sarj/require-interface-for-exported-class": "warn";
|
|
595
595
|
readonly "@sarj/require-port-for-service": "error";
|
|
@@ -606,7 +606,7 @@ declare const RECOMMENDED_RULES: {
|
|
|
606
606
|
readonly "@sarj/require-pascal-case-zod-schema-name": "error";
|
|
607
607
|
};
|
|
608
608
|
declare const STRICT_RULES: {
|
|
609
|
-
readonly "@sarj/named-child-schema-type": "
|
|
609
|
+
readonly "@sarj/named-child-schema-type": "error";
|
|
610
610
|
readonly "@sarj/no-conditional-empty-object-spread": "error";
|
|
611
611
|
readonly "@sarj/prefer-typed-reflection": "error";
|
|
612
612
|
readonly "@sarj/no-broad-return-type": "error";
|
|
@@ -887,7 +887,7 @@ declare const STRICT_RULES: {
|
|
|
887
887
|
}];
|
|
888
888
|
readonly "@sarj/prefer-named-callback-domain": "error";
|
|
889
889
|
readonly "@sarj/prefer-nominal-id-types": "warn";
|
|
890
|
-
readonly "@sarj/prefer-named-complex-return-type": "
|
|
890
|
+
readonly "@sarj/prefer-named-complex-return-type": "error";
|
|
891
891
|
readonly "@sarj/prefer-node-crypto-hash": "warn";
|
|
892
892
|
readonly "@sarj/prefer-node-fs-promises": "warn";
|
|
893
893
|
readonly "@sarj/prefer-non-nullable-collection": "error";
|
|
@@ -895,7 +895,7 @@ declare const STRICT_RULES: {
|
|
|
895
895
|
readonly "@sarj/prefer-await-in-async-return": "error";
|
|
896
896
|
readonly "@sarj/prefer-schema-for-api-payload": "error";
|
|
897
897
|
readonly "@sarj/prefer-shared-zod-enum": "warn";
|
|
898
|
-
readonly "@sarj/prefer-switch-for-repeated-equality": "
|
|
898
|
+
readonly "@sarj/prefer-switch-for-repeated-equality": "error";
|
|
899
899
|
readonly "@sarj/prefer-semantic-colors": readonly ["error", {
|
|
900
900
|
readonly requireSemanticTokens: true;
|
|
901
901
|
}];
|
|
@@ -906,7 +906,7 @@ declare const STRICT_RULES: {
|
|
|
906
906
|
readonly "@sarj/prefer-zod-parse-output-type": "error";
|
|
907
907
|
readonly "@sarj/require-assert-never": "error";
|
|
908
908
|
readonly "@sarj/require-fetch-timeout": "error";
|
|
909
|
-
readonly "@sarj/require-explicit-contract-implementation": "
|
|
909
|
+
readonly "@sarj/require-explicit-contract-implementation": "error";
|
|
910
910
|
readonly "@sarj/require-explicit-service-contract": "warn";
|
|
911
911
|
readonly "@sarj/require-interface-for-exported-class": "warn";
|
|
912
912
|
readonly "@sarj/require-port-for-service": "error";
|