@sarj/eslint-plugin 16.2.4 → 16.2.5
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 +42 -17
- package/dist/index.d.cts +7 -3
- package/dist/index.d.ts +7 -3
- package/dist/index.js +42 -17
- package/package.json +1 -1
package/dist/index.cjs
CHANGED
|
@@ -17622,15 +17622,16 @@ var prefer_nullish_filter_predicate_default = createRule({
|
|
|
17622
17622
|
var import_utils103 = require("@typescript-eslint/utils");
|
|
17623
17623
|
var ts11 = __toESM(require("typescript"), 1);
|
|
17624
17624
|
var PREFER_AWAIT_IN_ASYNC_RETURN_DOCUMENTATION = {
|
|
17625
|
-
summary: "Prefer explicit `await`
|
|
17626
|
-
rationale: "
|
|
17625
|
+
summary: "Prefer explicit `await` for proven Promise `.then` calls; the default scope checks direct async returns.",
|
|
17626
|
+
rationale: "Promise callback chains mix explicit async control flow with nested callbacks, making sequencing and failure handling harder to read.",
|
|
17627
17627
|
remediation: "Consider awaiting the Promise and returning the transformed value with ordinary async statements. Preserve catch boundaries, callback behavior, and observable scheduling when rewriting manually.",
|
|
17628
17628
|
category: "maintainability",
|
|
17629
17629
|
since: "15.6.3",
|
|
17630
17630
|
limitations: [
|
|
17631
|
-
"
|
|
17632
|
-
"The receiver must be proven Promise-like by TypeScript; an earlier chain can still produce that receiver.
|
|
17633
|
-
"
|
|
17631
|
+
"The default async-return scope checks one directly returned `.then` call with an inline callback. The all-promise-calls scope checks direct calls to built-in Promise/PromiseLike.then, including optional and literal-computed calls, without automatic rewrites.",
|
|
17632
|
+
"The receiver must be proven Promise-like by TypeScript; an earlier chain can still produce that receiver. The default async-return scope excludes rejection handlers and named callbacks. This is not the upstream return-await policy and no scheduling equivalence is promised.",
|
|
17633
|
+
"The default async-return scope excludes direct loader callbacks passed to resolved `React.lazy` and `next/dynamic` imports because returning the module Promise is their framework contract.",
|
|
17634
|
+
"All-promise-calls requires type information and excludes unproven/custom thenables, dynamic property names, property reads, destructuring, and extracted method aliases. Catch and finally remain available. Framework callback exclusions apply only to the default async-return scope."
|
|
17634
17635
|
],
|
|
17635
17636
|
examples: [
|
|
17636
17637
|
{
|
|
@@ -17687,15 +17688,28 @@ function promiseThenReceiver(node) {
|
|
|
17687
17688
|
}
|
|
17688
17689
|
return callee.object;
|
|
17689
17690
|
}
|
|
17691
|
+
function directThenReceiver(node) {
|
|
17692
|
+
const callee = node.callee;
|
|
17693
|
+
if (callee.type !== import_utils103.AST_NODE_TYPES.MemberExpression) return null;
|
|
17694
|
+
const property = callee.property;
|
|
17695
|
+
const isThen = callee.computed ? property.type === import_utils103.AST_NODE_TYPES.Literal && property.value === "then" || property.type === import_utils103.AST_NODE_TYPES.TemplateLiteral && property.expressions.length === 0 && property.quasis[0]?.value.cooked === "then" : property.type === import_utils103.AST_NODE_TYPES.Identifier && property.name === "then";
|
|
17696
|
+
return isThen ? callee.object : null;
|
|
17697
|
+
}
|
|
17690
17698
|
function isProvenPromiseLike(node, services) {
|
|
17691
17699
|
const checker = services.program.getTypeChecker();
|
|
17692
17700
|
const tsNode = services.esTreeNodeToTSNodeMap.get(node);
|
|
17693
|
-
const receiverType = checker.getTypeAtLocation(tsNode);
|
|
17694
|
-
|
|
17701
|
+
const receiverType = checker.getNonNullableType(checker.getTypeAtLocation(tsNode));
|
|
17702
|
+
const members = receiverType.isUnion() ? receiverType.types : [receiverType];
|
|
17703
|
+
return members.every((member) => isBuiltInPromiseType(member, services));
|
|
17704
|
+
}
|
|
17705
|
+
function isBuiltInPromiseType(type, services) {
|
|
17706
|
+
if ((type.flags & (ts11.TypeFlags.Any | ts11.TypeFlags.Unknown | ts11.TypeFlags.Never)) !== 0) {
|
|
17695
17707
|
return false;
|
|
17696
17708
|
}
|
|
17697
|
-
const thenSymbol =
|
|
17698
|
-
const
|
|
17709
|
+
const thenSymbol = services.program.getTypeChecker().getPropertyOfType(type, "then");
|
|
17710
|
+
const declarations = thenSymbol?.declarations;
|
|
17711
|
+
if (declarations === void 0 || declarations.length === 0) return false;
|
|
17712
|
+
return declarations.every(
|
|
17699
17713
|
(declaration) => {
|
|
17700
17714
|
let owner = declaration.parent;
|
|
17701
17715
|
while (owner !== void 0 && !ts11.isInterfaceDeclaration(owner)) {
|
|
@@ -17703,8 +17717,7 @@ function isProvenPromiseLike(node, services) {
|
|
|
17703
17717
|
}
|
|
17704
17718
|
return owner !== void 0 && (owner.name.text === "Promise" || owner.name.text === "PromiseLike") && services.program.isSourceFileDefaultLibrary(owner.getSourceFile());
|
|
17705
17719
|
}
|
|
17706
|
-
)
|
|
17707
|
-
return hasBuiltInPromiseDeclaration;
|
|
17720
|
+
);
|
|
17708
17721
|
}
|
|
17709
17722
|
var prefer_await_in_async_return_default = createRule({
|
|
17710
17723
|
name: "prefer-await-in-async-return",
|
|
@@ -17712,15 +17725,20 @@ var prefer_await_in_async_return_default = createRule({
|
|
|
17712
17725
|
meta: {
|
|
17713
17726
|
type: "suggestion",
|
|
17714
17727
|
docs: {
|
|
17715
|
-
description: "Prefer explicit `await`
|
|
17728
|
+
description: "Prefer explicit `await` for proven Promise `.then` calls; the default scope checks direct async returns."
|
|
17716
17729
|
},
|
|
17717
|
-
schema: [
|
|
17730
|
+
schema: [{
|
|
17731
|
+
type: "object",
|
|
17732
|
+
properties: { scope: { type: "string", enum: ["async-return", "all-promise-calls"] } },
|
|
17733
|
+
additionalProperties: false
|
|
17734
|
+
}],
|
|
17718
17735
|
messages: {
|
|
17719
|
-
preferAwait: "This async function directly returns a Promise `.then` transform. Await the Promise, then return the transformed value with explicit async control flow."
|
|
17736
|
+
preferAwait: "This async function directly returns a Promise `.then` transform. Await the Promise, then return the transformed value with explicit async control flow.",
|
|
17737
|
+
preferAwaitCall: "This call uses built-in Promise.then(). Use async/await, preserving rejection handling and observable scheduling when rewriting."
|
|
17720
17738
|
}
|
|
17721
17739
|
},
|
|
17722
|
-
defaultOptions: [],
|
|
17723
|
-
create(context) {
|
|
17740
|
+
defaultOptions: [{ scope: "async-return" }],
|
|
17741
|
+
create(context, [options]) {
|
|
17724
17742
|
let services;
|
|
17725
17743
|
try {
|
|
17726
17744
|
services = import_utils103.ESLintUtils.getParserServices(context);
|
|
@@ -17753,6 +17771,13 @@ var prefer_await_in_async_return_default = createRule({
|
|
|
17753
17771
|
}
|
|
17754
17772
|
},
|
|
17755
17773
|
CallExpression(node) {
|
|
17774
|
+
if (options.scope === "all-promise-calls") {
|
|
17775
|
+
const receiver2 = directThenReceiver(node);
|
|
17776
|
+
if (receiver2 !== null && isProvenPromiseLike(receiver2, services)) {
|
|
17777
|
+
context.report({ node, messageId: "preferAwaitCall" });
|
|
17778
|
+
}
|
|
17779
|
+
return;
|
|
17780
|
+
}
|
|
17756
17781
|
const owner = directAsyncReturnOwner(node);
|
|
17757
17782
|
if (owner === null || isFrameworkLoaderCallback(owner)) return;
|
|
17758
17783
|
const receiver = promiseThenReceiver(node);
|
|
@@ -23808,7 +23833,7 @@ var RULES = {
|
|
|
23808
23833
|
};
|
|
23809
23834
|
var meta = {
|
|
23810
23835
|
name: "@sarj/eslint-plugin",
|
|
23811
|
-
version: "16.2.
|
|
23836
|
+
version: "16.2.5"
|
|
23812
23837
|
};
|
|
23813
23838
|
var APPLICATION_ONLY_RULES = [];
|
|
23814
23839
|
var LIBRARY_IMPORT_POLICY = ["error", {
|
package/dist/index.d.cts
CHANGED
|
@@ -253,7 +253,9 @@ declare const RULES: {
|
|
|
253
253
|
readonly "prefer-node-fs-promises": DocumentedRule<[], "preferAsyncFs">;
|
|
254
254
|
readonly "prefer-non-nullable-collection": DocumentedRule<readonly [], "preferNonNullableCollection">;
|
|
255
255
|
readonly "prefer-nullish-filter-predicate": DocumentedRule<readonly [], "preferNullishPredicate" | "replaceBoolean">;
|
|
256
|
-
readonly "prefer-await-in-async-return": DocumentedRule<readonly [
|
|
256
|
+
readonly "prefer-await-in-async-return": DocumentedRule<readonly [{
|
|
257
|
+
readonly scope: "async-return" | "all-promise-calls";
|
|
258
|
+
}], "preferAwait" | "preferAwaitCall">;
|
|
257
259
|
readonly "prefer-schema-for-api-payload": DocumentedRule<readonly [], "unparsedJsonAccess">;
|
|
258
260
|
readonly "prefer-shared-zod-enum": DocumentedRule<[], "shareEnumDomain">;
|
|
259
261
|
readonly "prefer-switch-for-repeated-equality": DocumentedRule<[], "preferSwitch">;
|
|
@@ -922,7 +924,7 @@ type FlatPreset = {
|
|
|
922
924
|
declare const PLUGIN: {
|
|
923
925
|
readonly meta: {
|
|
924
926
|
readonly name: "@sarj/eslint-plugin";
|
|
925
|
-
readonly version: "16.2.
|
|
927
|
+
readonly version: "16.2.5";
|
|
926
928
|
};
|
|
927
929
|
readonly rules: {
|
|
928
930
|
readonly "require-explicit-contract-implementation": DocumentedRule<readonly [], "declareActualContract">;
|
|
@@ -1052,7 +1054,9 @@ declare const PLUGIN: {
|
|
|
1052
1054
|
readonly "prefer-node-fs-promises": DocumentedRule<[], "preferAsyncFs">;
|
|
1053
1055
|
readonly "prefer-non-nullable-collection": DocumentedRule<readonly [], "preferNonNullableCollection">;
|
|
1054
1056
|
readonly "prefer-nullish-filter-predicate": DocumentedRule<readonly [], "preferNullishPredicate" | "replaceBoolean">;
|
|
1055
|
-
readonly "prefer-await-in-async-return": DocumentedRule<readonly [
|
|
1057
|
+
readonly "prefer-await-in-async-return": DocumentedRule<readonly [{
|
|
1058
|
+
readonly scope: "async-return" | "all-promise-calls";
|
|
1059
|
+
}], "preferAwait" | "preferAwaitCall">;
|
|
1056
1060
|
readonly "prefer-schema-for-api-payload": DocumentedRule<readonly [], "unparsedJsonAccess">;
|
|
1057
1061
|
readonly "prefer-shared-zod-enum": DocumentedRule<[], "shareEnumDomain">;
|
|
1058
1062
|
readonly "prefer-switch-for-repeated-equality": DocumentedRule<[], "preferSwitch">;
|
package/dist/index.d.ts
CHANGED
|
@@ -253,7 +253,9 @@ declare const RULES: {
|
|
|
253
253
|
readonly "prefer-node-fs-promises": DocumentedRule<[], "preferAsyncFs">;
|
|
254
254
|
readonly "prefer-non-nullable-collection": DocumentedRule<readonly [], "preferNonNullableCollection">;
|
|
255
255
|
readonly "prefer-nullish-filter-predicate": DocumentedRule<readonly [], "preferNullishPredicate" | "replaceBoolean">;
|
|
256
|
-
readonly "prefer-await-in-async-return": DocumentedRule<readonly [
|
|
256
|
+
readonly "prefer-await-in-async-return": DocumentedRule<readonly [{
|
|
257
|
+
readonly scope: "async-return" | "all-promise-calls";
|
|
258
|
+
}], "preferAwait" | "preferAwaitCall">;
|
|
257
259
|
readonly "prefer-schema-for-api-payload": DocumentedRule<readonly [], "unparsedJsonAccess">;
|
|
258
260
|
readonly "prefer-shared-zod-enum": DocumentedRule<[], "shareEnumDomain">;
|
|
259
261
|
readonly "prefer-switch-for-repeated-equality": DocumentedRule<[], "preferSwitch">;
|
|
@@ -922,7 +924,7 @@ type FlatPreset = {
|
|
|
922
924
|
declare const PLUGIN: {
|
|
923
925
|
readonly meta: {
|
|
924
926
|
readonly name: "@sarj/eslint-plugin";
|
|
925
|
-
readonly version: "16.2.
|
|
927
|
+
readonly version: "16.2.5";
|
|
926
928
|
};
|
|
927
929
|
readonly rules: {
|
|
928
930
|
readonly "require-explicit-contract-implementation": DocumentedRule<readonly [], "declareActualContract">;
|
|
@@ -1052,7 +1054,9 @@ declare const PLUGIN: {
|
|
|
1052
1054
|
readonly "prefer-node-fs-promises": DocumentedRule<[], "preferAsyncFs">;
|
|
1053
1055
|
readonly "prefer-non-nullable-collection": DocumentedRule<readonly [], "preferNonNullableCollection">;
|
|
1054
1056
|
readonly "prefer-nullish-filter-predicate": DocumentedRule<readonly [], "preferNullishPredicate" | "replaceBoolean">;
|
|
1055
|
-
readonly "prefer-await-in-async-return": DocumentedRule<readonly [
|
|
1057
|
+
readonly "prefer-await-in-async-return": DocumentedRule<readonly [{
|
|
1058
|
+
readonly scope: "async-return" | "all-promise-calls";
|
|
1059
|
+
}], "preferAwait" | "preferAwaitCall">;
|
|
1056
1060
|
readonly "prefer-schema-for-api-payload": DocumentedRule<readonly [], "unparsedJsonAccess">;
|
|
1057
1061
|
readonly "prefer-shared-zod-enum": DocumentedRule<[], "shareEnumDomain">;
|
|
1058
1062
|
readonly "prefer-switch-for-repeated-equality": DocumentedRule<[], "preferSwitch">;
|
package/dist/index.js
CHANGED
|
@@ -17631,15 +17631,16 @@ import {
|
|
|
17631
17631
|
} from "@typescript-eslint/utils";
|
|
17632
17632
|
import * as ts11 from "typescript";
|
|
17633
17633
|
var PREFER_AWAIT_IN_ASYNC_RETURN_DOCUMENTATION = {
|
|
17634
|
-
summary: "Prefer explicit `await`
|
|
17635
|
-
rationale: "
|
|
17634
|
+
summary: "Prefer explicit `await` for proven Promise `.then` calls; the default scope checks direct async returns.",
|
|
17635
|
+
rationale: "Promise callback chains mix explicit async control flow with nested callbacks, making sequencing and failure handling harder to read.",
|
|
17636
17636
|
remediation: "Consider awaiting the Promise and returning the transformed value with ordinary async statements. Preserve catch boundaries, callback behavior, and observable scheduling when rewriting manually.",
|
|
17637
17637
|
category: "maintainability",
|
|
17638
17638
|
since: "15.6.3",
|
|
17639
17639
|
limitations: [
|
|
17640
|
-
"
|
|
17641
|
-
"The receiver must be proven Promise-like by TypeScript; an earlier chain can still produce that receiver.
|
|
17642
|
-
"
|
|
17640
|
+
"The default async-return scope checks one directly returned `.then` call with an inline callback. The all-promise-calls scope checks direct calls to built-in Promise/PromiseLike.then, including optional and literal-computed calls, without automatic rewrites.",
|
|
17641
|
+
"The receiver must be proven Promise-like by TypeScript; an earlier chain can still produce that receiver. The default async-return scope excludes rejection handlers and named callbacks. This is not the upstream return-await policy and no scheduling equivalence is promised.",
|
|
17642
|
+
"The default async-return scope excludes direct loader callbacks passed to resolved `React.lazy` and `next/dynamic` imports because returning the module Promise is their framework contract.",
|
|
17643
|
+
"All-promise-calls requires type information and excludes unproven/custom thenables, dynamic property names, property reads, destructuring, and extracted method aliases. Catch and finally remain available. Framework callback exclusions apply only to the default async-return scope."
|
|
17643
17644
|
],
|
|
17644
17645
|
examples: [
|
|
17645
17646
|
{
|
|
@@ -17696,15 +17697,28 @@ function promiseThenReceiver(node) {
|
|
|
17696
17697
|
}
|
|
17697
17698
|
return callee.object;
|
|
17698
17699
|
}
|
|
17700
|
+
function directThenReceiver(node) {
|
|
17701
|
+
const callee = node.callee;
|
|
17702
|
+
if (callee.type !== AST_NODE_TYPES86.MemberExpression) return null;
|
|
17703
|
+
const property = callee.property;
|
|
17704
|
+
const isThen = callee.computed ? property.type === AST_NODE_TYPES86.Literal && property.value === "then" || property.type === AST_NODE_TYPES86.TemplateLiteral && property.expressions.length === 0 && property.quasis[0]?.value.cooked === "then" : property.type === AST_NODE_TYPES86.Identifier && property.name === "then";
|
|
17705
|
+
return isThen ? callee.object : null;
|
|
17706
|
+
}
|
|
17699
17707
|
function isProvenPromiseLike(node, services) {
|
|
17700
17708
|
const checker = services.program.getTypeChecker();
|
|
17701
17709
|
const tsNode = services.esTreeNodeToTSNodeMap.get(node);
|
|
17702
|
-
const receiverType = checker.getTypeAtLocation(tsNode);
|
|
17703
|
-
|
|
17710
|
+
const receiverType = checker.getNonNullableType(checker.getTypeAtLocation(tsNode));
|
|
17711
|
+
const members = receiverType.isUnion() ? receiverType.types : [receiverType];
|
|
17712
|
+
return members.every((member) => isBuiltInPromiseType(member, services));
|
|
17713
|
+
}
|
|
17714
|
+
function isBuiltInPromiseType(type, services) {
|
|
17715
|
+
if ((type.flags & (ts11.TypeFlags.Any | ts11.TypeFlags.Unknown | ts11.TypeFlags.Never)) !== 0) {
|
|
17704
17716
|
return false;
|
|
17705
17717
|
}
|
|
17706
|
-
const thenSymbol =
|
|
17707
|
-
const
|
|
17718
|
+
const thenSymbol = services.program.getTypeChecker().getPropertyOfType(type, "then");
|
|
17719
|
+
const declarations = thenSymbol?.declarations;
|
|
17720
|
+
if (declarations === void 0 || declarations.length === 0) return false;
|
|
17721
|
+
return declarations.every(
|
|
17708
17722
|
(declaration) => {
|
|
17709
17723
|
let owner = declaration.parent;
|
|
17710
17724
|
while (owner !== void 0 && !ts11.isInterfaceDeclaration(owner)) {
|
|
@@ -17712,8 +17726,7 @@ function isProvenPromiseLike(node, services) {
|
|
|
17712
17726
|
}
|
|
17713
17727
|
return owner !== void 0 && (owner.name.text === "Promise" || owner.name.text === "PromiseLike") && services.program.isSourceFileDefaultLibrary(owner.getSourceFile());
|
|
17714
17728
|
}
|
|
17715
|
-
)
|
|
17716
|
-
return hasBuiltInPromiseDeclaration;
|
|
17729
|
+
);
|
|
17717
17730
|
}
|
|
17718
17731
|
var prefer_await_in_async_return_default = createRule({
|
|
17719
17732
|
name: "prefer-await-in-async-return",
|
|
@@ -17721,15 +17734,20 @@ var prefer_await_in_async_return_default = createRule({
|
|
|
17721
17734
|
meta: {
|
|
17722
17735
|
type: "suggestion",
|
|
17723
17736
|
docs: {
|
|
17724
|
-
description: "Prefer explicit `await`
|
|
17737
|
+
description: "Prefer explicit `await` for proven Promise `.then` calls; the default scope checks direct async returns."
|
|
17725
17738
|
},
|
|
17726
|
-
schema: [
|
|
17739
|
+
schema: [{
|
|
17740
|
+
type: "object",
|
|
17741
|
+
properties: { scope: { type: "string", enum: ["async-return", "all-promise-calls"] } },
|
|
17742
|
+
additionalProperties: false
|
|
17743
|
+
}],
|
|
17727
17744
|
messages: {
|
|
17728
|
-
preferAwait: "This async function directly returns a Promise `.then` transform. Await the Promise, then return the transformed value with explicit async control flow."
|
|
17745
|
+
preferAwait: "This async function directly returns a Promise `.then` transform. Await the Promise, then return the transformed value with explicit async control flow.",
|
|
17746
|
+
preferAwaitCall: "This call uses built-in Promise.then(). Use async/await, preserving rejection handling and observable scheduling when rewriting."
|
|
17729
17747
|
}
|
|
17730
17748
|
},
|
|
17731
|
-
defaultOptions: [],
|
|
17732
|
-
create(context) {
|
|
17749
|
+
defaultOptions: [{ scope: "async-return" }],
|
|
17750
|
+
create(context, [options]) {
|
|
17733
17751
|
let services;
|
|
17734
17752
|
try {
|
|
17735
17753
|
services = ESLintUtils13.getParserServices(context);
|
|
@@ -17762,6 +17780,13 @@ var prefer_await_in_async_return_default = createRule({
|
|
|
17762
17780
|
}
|
|
17763
17781
|
},
|
|
17764
17782
|
CallExpression(node) {
|
|
17783
|
+
if (options.scope === "all-promise-calls") {
|
|
17784
|
+
const receiver2 = directThenReceiver(node);
|
|
17785
|
+
if (receiver2 !== null && isProvenPromiseLike(receiver2, services)) {
|
|
17786
|
+
context.report({ node, messageId: "preferAwaitCall" });
|
|
17787
|
+
}
|
|
17788
|
+
return;
|
|
17789
|
+
}
|
|
17765
17790
|
const owner = directAsyncReturnOwner(node);
|
|
17766
17791
|
if (owner === null || isFrameworkLoaderCallback(owner)) return;
|
|
17767
17792
|
const receiver = promiseThenReceiver(node);
|
|
@@ -23829,7 +23854,7 @@ var RULES = {
|
|
|
23829
23854
|
};
|
|
23830
23855
|
var meta = {
|
|
23831
23856
|
name: "@sarj/eslint-plugin",
|
|
23832
|
-
version: "16.2.
|
|
23857
|
+
version: "16.2.5"
|
|
23833
23858
|
};
|
|
23834
23859
|
var APPLICATION_ONLY_RULES = [];
|
|
23835
23860
|
var LIBRARY_IMPORT_POLICY = ["error", {
|