@sarj/eslint-plugin 19.10.0 → 19.12.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/catalog.js +32 -2
- package/dist/{chunk-ZWOGM4CV.js → chunk-7SYRLUE7.js} +35 -22
- package/dist/index.js +1 -1
- package/package.json +1 -1
package/dist/catalog.js
CHANGED
|
@@ -2,7 +2,7 @@ import {
|
|
|
2
2
|
publicDocumentation,
|
|
3
3
|
ruleSpec,
|
|
4
4
|
src_default
|
|
5
|
-
} from "./chunk-
|
|
5
|
+
} from "./chunk-7SYRLUE7.js";
|
|
6
6
|
|
|
7
7
|
// src/docs/directive-disable-enable-pair.ts
|
|
8
8
|
var DIRECTIVE_DISABLE_ENABLE_PAIR_DOCUMENTATION = {
|
|
@@ -4163,7 +4163,7 @@ var PREFER_CODED_ERROR_RESULT_DOCUMENTATION = {
|
|
|
4163
4163
|
"Checks source-resolved local unions with required literal ok/success booleans, or status/state/kind/type/tag values ok/success versus err/error/failure/failed (case insensitive). Conflicting outcome tags abstain. A shared outcome tag does not also count as a domain error code. Named and namespace neverthrow Result/ResultAsync imports establish their generic error position.",
|
|
4164
4164
|
"Presence-selected unions require an error property on every failure branch and the same single required non-control value property on every success branch. Optional error/value fields, multiple value keys, loading states and error branches carrying the success value abstain. Required errorMessage and Error-suffixed failure channels are also reviewed; multiple custom channels abstain and a primary error payload retains precedence.",
|
|
4165
4165
|
"Broad string and unknown error channels, unshadowed native Error-family types and open string/unknown code fields receive review. Explicit Any stays with the existing no-explicit-any rule. Finite literal codes need no invented payload. Imported domain errors, validation-library errors, generic error parameters, ordinary formatters, legitimate absence and redacted failure states remain valid.",
|
|
4166
|
-
"Local aliases, unmerged interfaces without inheritance and generic substitutions are bounded to 16 resolution levels, 64 union members and 256 traversal steps. Imported local declarations, conditional/intersection/mapped types and unresolved contracts abstain. Optional discriminants, independent success/error payloads and partial-data failures are excluded.",
|
|
4166
|
+
"Local aliases, unmerged interfaces without inheritance and generic substitutions are bounded to 16 resolution levels, 64 union members and 256 traversal steps. Transparent aliases retain the proven neverthrow Result/ResultAsync error position, including renamed/namespace imports, generic defaults and unshadowed native Promise/PromiseLike wrappers. Imported local declarations, conditional/intersection/mapped types and unresolved contracts abstain. Optional discriminants, independent success/error payloads and partial-data failures are excluded.",
|
|
4167
4167
|
"Required code/kind/type/tag fields of unresolved or imported type defer to the type checker; a finite code does not prove that its cases or payloads are useful. Generic error parameters are retained rather than guessed. Ordinary string formatters, absence, validation-library errors and redacted failure states without a string payload are not flagged.",
|
|
4168
4168
|
"A directly returned failure object, neverthrow err/errAsync call or new Err with an interpolated template or proven string concatenation receives review. Without a code, the diagnostic asks for a domain contract; with a literal code, it asks for consumer formatting. Literal-only compositions, including earlier stable local constants, remain valid codes. Nested plain error objects, expression-bodied arrows and one direct await are supported. Import identity and value-space shadowing are checked; arbitrary aliases, spreads, accessors, computed keys, helper formatting calls and nonliteral codes abstain. This proves formatting ownership, not which context the domain must expose; presentation adapters remain a reviewed exception.",
|
|
4169
4169
|
"This warning requests domain review: an infrastructure adapter may intentionally retain unknown/Error, and a final presentation boundary may accept every failure and render one message. Neither proves a recoverable domain rejection. No fix invents error codes, fields, handlers or changes serialization, exception unwinding, transactions, retries or logging."
|
|
@@ -4173,6 +4173,36 @@ var PREFER_CODED_ERROR_RESULT_DOCUMENTATION = {
|
|
|
4173
4173
|
"https://github.com/supermacro/neverthrow"
|
|
4174
4174
|
],
|
|
4175
4175
|
examples: [
|
|
4176
|
+
{
|
|
4177
|
+
id: "aliased-library-message",
|
|
4178
|
+
scenarioId: "aliased-library-error",
|
|
4179
|
+
title: "A transparent alias must preserve the library error contract",
|
|
4180
|
+
outcome: "match",
|
|
4181
|
+
files: [
|
|
4182
|
+
{
|
|
4183
|
+
path: "app/result.ts",
|
|
4184
|
+
source: "import type { Result as NativeResult } from 'neverthrow'; type Saved<T, E> = Promise<NativeResult<T, E>>; export type Output = Saved<number, string>;"
|
|
4185
|
+
}
|
|
4186
|
+
],
|
|
4187
|
+
focusPath: "app/result.ts",
|
|
4188
|
+
expectedCount: 1,
|
|
4189
|
+
public: true
|
|
4190
|
+
},
|
|
4191
|
+
{
|
|
4192
|
+
id: "aliased-library-domain-error",
|
|
4193
|
+
scenarioId: "aliased-library-error",
|
|
4194
|
+
title: "Keep a finite error code and only the context its consumer needs",
|
|
4195
|
+
outcome: "no-match",
|
|
4196
|
+
files: [
|
|
4197
|
+
{
|
|
4198
|
+
path: "app/result.ts",
|
|
4199
|
+
source: "import type { Result as NativeResult } from 'neverthrow'; type Saved<T, E> = Promise<NativeResult<T, E>>; export type Output = Saved<number, { code: 'duplicate'; name: string } | { code: 'denied' }>;"
|
|
4200
|
+
}
|
|
4201
|
+
],
|
|
4202
|
+
focusPath: "app/result.ts",
|
|
4203
|
+
expectedCount: 0,
|
|
4204
|
+
public: true
|
|
4205
|
+
},
|
|
4176
4206
|
{
|
|
4177
4207
|
id: "presence-selected-message",
|
|
4178
4208
|
scenarioId: "presence-selected-result",
|
|
@@ -21588,14 +21588,15 @@ function resolve2(value, source, depth = 0) {
|
|
|
21588
21588
|
if (depth >= MAX_DEPTH) return null;
|
|
21589
21589
|
const node = value.node;
|
|
21590
21590
|
if (node.type !== "TSTypeReference") return value;
|
|
21591
|
-
if (node.typeName.type !== "Identifier")
|
|
21591
|
+
if (node.typeName.type !== "Identifier")
|
|
21592
|
+
return libraryResult(node, source) ? value : null;
|
|
21592
21593
|
const variable = typeBinding(source, node.typeName);
|
|
21593
21594
|
if (variable === null || variable.defs.length === 0) return value;
|
|
21594
21595
|
const bound = value.bindings.get(variable);
|
|
21595
21596
|
if (bound !== void 0) return resolve2(bound, source, depth + 1);
|
|
21596
21597
|
const declaration = variable.defs.length === 1 ? variable.defs[0]?.node : void 0;
|
|
21597
21598
|
if (declaration?.type !== "TSTypeAliasDeclaration" && declaration?.type !== "TSInterfaceDeclaration")
|
|
21598
|
-
return null;
|
|
21599
|
+
return libraryResult(node, source) ? value : null;
|
|
21599
21600
|
if (declaration.type === "TSInterfaceDeclaration" && declaration.extends.length !== 0)
|
|
21600
21601
|
return null;
|
|
21601
21602
|
const bindings = bindArguments(declaration, node, value, source);
|
|
@@ -21761,6 +21762,26 @@ function openStringField(fields2, owner, source, names, budget) {
|
|
|
21761
21762
|
}
|
|
21762
21763
|
return null;
|
|
21763
21764
|
}
|
|
21765
|
+
function outcomeFailures(value, source, depth = 0, budget = { remaining: MAX_TYPE_STEPS }) {
|
|
21766
|
+
if (depth >= MAX_DEPTH || --budget.remaining < 0) return [];
|
|
21767
|
+
const resolved = resolve2(value, source);
|
|
21768
|
+
if (resolved === null) return [];
|
|
21769
|
+
const structural = failureMessages(resolved, source);
|
|
21770
|
+
if (structural.length !== 0) return structural;
|
|
21771
|
+
const library = libraryError(resolved, source);
|
|
21772
|
+
if (library !== null) return [library];
|
|
21773
|
+
const node = resolved.node;
|
|
21774
|
+
if (node.type !== "TSTypeReference") return [];
|
|
21775
|
+
if (node.typeName.type !== "Identifier" || !["Promise", "PromiseLike"].includes(node.typeName.name) || (typeBinding(source, node.typeName)?.defs.length ?? 0) !== 0 || node.typeArguments?.params.length !== 1)
|
|
21776
|
+
return [];
|
|
21777
|
+
const argument = node.typeArguments.params[0];
|
|
21778
|
+
return argument === void 0 ? [] : outcomeFailures(
|
|
21779
|
+
{ ...resolved, node: argument, origin: argument },
|
|
21780
|
+
source,
|
|
21781
|
+
depth + 1,
|
|
21782
|
+
budget
|
|
21783
|
+
);
|
|
21784
|
+
}
|
|
21764
21785
|
function failureMessages(value, source) {
|
|
21765
21786
|
const members2 = variants(value, source);
|
|
21766
21787
|
if (members2 === null || members2.length < 2) return [];
|
|
@@ -21853,14 +21874,18 @@ function variants(value, source, depth = 0, budget = { remaining: MAX_TYPE_STEPS
|
|
|
21853
21874
|
}
|
|
21854
21875
|
return result;
|
|
21855
21876
|
}
|
|
21856
|
-
function libraryError(
|
|
21857
|
-
|
|
21858
|
-
if (
|
|
21859
|
-
libraryName(reference.typeName, source, true) ?? ""
|
|
21860
|
-
))
|
|
21877
|
+
function libraryError(value, source) {
|
|
21878
|
+
const reference = value.node;
|
|
21879
|
+
if (reference.type !== "TSTypeReference" || !libraryResult(reference, source))
|
|
21861
21880
|
return null;
|
|
21881
|
+
if (reference.typeArguments?.params.length !== 2) return null;
|
|
21862
21882
|
const error = reference.typeArguments.params[1];
|
|
21863
|
-
return error === void 0 ? null : weakError(
|
|
21883
|
+
return error === void 0 ? null : weakError({ ...value, node: error, origin: error }, source);
|
|
21884
|
+
}
|
|
21885
|
+
function libraryResult(reference, source) {
|
|
21886
|
+
return ["Result", "ResultAsync"].includes(
|
|
21887
|
+
libraryName(reference.typeName, source, true) ?? ""
|
|
21888
|
+
);
|
|
21864
21889
|
}
|
|
21865
21890
|
function libraryName(node, source, typeSpace) {
|
|
21866
21891
|
const reference = libraryReference(node);
|
|
@@ -21886,16 +21911,6 @@ function libraryReference(node) {
|
|
|
21886
21911
|
return { root: node.object, member: node.property.name };
|
|
21887
21912
|
return null;
|
|
21888
21913
|
}
|
|
21889
|
-
function weakAnnotation(node, source, depth = 0, budget = { remaining: MAX_TYPE_STEPS }) {
|
|
21890
|
-
if (depth >= MAX_DEPTH || --budget.remaining < 0) return false;
|
|
21891
|
-
if (failureMessages(view(node), source).length !== 0) return true;
|
|
21892
|
-
if (node.type !== "TSTypeReference") return false;
|
|
21893
|
-
if (libraryError(node, source) !== null) return true;
|
|
21894
|
-
if (node.typeName.type !== "Identifier" || !["Promise", "PromiseLike"].includes(node.typeName.name) || typeBinding(source, node.typeName) !== null || node.typeArguments?.params.length !== 1)
|
|
21895
|
-
return false;
|
|
21896
|
-
const argument = node.typeArguments.params[0];
|
|
21897
|
-
return argument !== void 0 && weakAnnotation(argument, source, depth + 1, budget);
|
|
21898
|
-
}
|
|
21899
21914
|
function renderedFailure(node, source) {
|
|
21900
21915
|
let value = unwrapExpression(node);
|
|
21901
21916
|
if (value.type === "AwaitExpression")
|
|
@@ -22017,9 +22032,7 @@ var prefer_coded_error_result_default = defineRule({
|
|
|
22017
22032
|
createOnce(context) {
|
|
22018
22033
|
const reported = /* @__PURE__ */ new Set();
|
|
22019
22034
|
function check(node) {
|
|
22020
|
-
const
|
|
22021
|
-
const library = node.type === "TSTypeReference" ? libraryError(node, context.sourceCode) : null;
|
|
22022
|
-
for (const candidate2 of library === null ? candidates2 : [...candidates2, library]) {
|
|
22035
|
+
for (const candidate2 of outcomeFailures(view(node), context.sourceCode)) {
|
|
22023
22036
|
if (reported.has(candidate2)) continue;
|
|
22024
22037
|
reported.add(candidate2);
|
|
22025
22038
|
context.report({
|
|
@@ -22033,7 +22046,7 @@ var prefer_coded_error_result_default = defineRule({
|
|
|
22033
22046
|
const rendered = renderedFailure(value, context.sourceCode);
|
|
22034
22047
|
if (rendered === null || reported.has(rendered.node)) return;
|
|
22035
22048
|
const contract = owner.returnType?.typeAnnotation;
|
|
22036
|
-
if (contract !== void 0 &&
|
|
22049
|
+
if (contract !== void 0 && outcomeFailures(view(contract), context.sourceCode).length !== 0)
|
|
22037
22050
|
return;
|
|
22038
22051
|
reported.add(rendered.node);
|
|
22039
22052
|
context.report(rendered);
|
package/dist/index.js
CHANGED