@sarj/eslint-plugin 19.0.2 → 19.2.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 CHANGED
@@ -2,7 +2,7 @@ import {
2
2
  publicDocumentation,
3
3
  ruleSpec,
4
4
  src_default
5
- } from "./chunk-KBGBBVAC.js";
5
+ } from "./chunk-JBAPB4JX.js";
6
6
 
7
7
  // src/docs/directive-disable-enable-pair.ts
8
8
  var DIRECTIVE_DISABLE_ENABLE_PAIR_DOCUMENTATION = {
@@ -4116,6 +4116,117 @@ var PREFER_AWAIT_IN_ASYNC_RETURN_DOCUMENTATION = {
4116
4116
  ]
4117
4117
  };
4118
4118
 
4119
+ // src/docs/prefer-coded-error-result.ts
4120
+ var PREFER_CODED_ERROR_RESULT_DOCUMENTATION = {
4121
+ summary: "Return a stable error code and typed context instead of only a rendered failure message.",
4122
+ defaultLevel: "warning",
4123
+ rationale: "A message-only failure hides the identity needed for repair, conflict handling, localization and exhaustive dispatch. Preserve a finite error code and the minimum handling context; let the consumer format its message.",
4124
+ remediation: "Use the existing Result or outcome union with a finite error code and variant-specific context. Preserve public behavior through a presentation adapter, and handle or propagate each relevant variant without parsing message text.",
4125
+ category: "correctness",
4126
+ autofix: "none",
4127
+ limitations: [
4128
+ "Checks source-resolved local unions with required literal ok/success true and false branches, and named neverthrow Result/ResultAsync imports. Broad string error/message/reason payloads and open string code fields are review candidates. String literal error-code unions remain valid.",
4129
+ "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, namespace imports, conditional/intersection/mapped types and unresolved contracts abstain. Optional discriminants, independent success/error payloads and partial-data failures are excluded.",
4130
+ "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.",
4131
+ "A directly returned plain object with literal ok/success false and a literal string code/kind/type/tag also receives review when its message/reason is an interpolated template or proven string concatenation. Nested plain error objects and expression-bodied arrows are supported. 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.",
4132
+ "This warning requests domain review: a final presentation boundary may intentionally accept every failure and render one message. No fix invents error codes, fields, handlers or changes serialization, exception unwinding, transactions, retries or logging."
4133
+ ],
4134
+ references: [
4135
+ "https://www.typescriptlang.org/docs/handbook/2/narrowing.html#discriminated-unions",
4136
+ "https://github.com/supermacro/neverthrow"
4137
+ ],
4138
+ examples: [
4139
+ {
4140
+ id: "message-only-result",
4141
+ title: "A failure erases identity into a message",
4142
+ outcome: "match",
4143
+ files: [
4144
+ {
4145
+ path: "app/result.ts",
4146
+ source: "export type Result<T> = { ok: true; data: T } | { ok: false; message: string };"
4147
+ }
4148
+ ],
4149
+ focusPath: "app/result.ts",
4150
+ expectedCount: 1,
4151
+ public: true
4152
+ },
4153
+ {
4154
+ id: "code-and-context",
4155
+ title: "The consumer can choose behavior and format context",
4156
+ outcome: "no-match",
4157
+ files: [
4158
+ {
4159
+ path: "app/result.ts",
4160
+ source: "type Error = { code: 'duplicate'; name: string } | { code: 'invalid_transition' }; export type Result<T> = { ok: true; data: T } | { ok: false; error: Error };"
4161
+ }
4162
+ ],
4163
+ focusPath: "app/result.ts",
4164
+ expectedCount: 0,
4165
+ public: true
4166
+ },
4167
+ {
4168
+ id: "generic-error-instantiation",
4169
+ scenarioId: "generic-error",
4170
+ title: "A concrete generic error channel erases its identity",
4171
+ outcome: "match",
4172
+ files: [
4173
+ {
4174
+ path: "app/result.ts",
4175
+ source: "type Result<T, E> = { ok: true; value: T } | { ok: false; error: E }; export type Saved = Result<number, string>;"
4176
+ }
4177
+ ],
4178
+ focusPath: "app/result.ts",
4179
+ expectedCount: 1,
4180
+ public: true
4181
+ },
4182
+ {
4183
+ id: "finite-error-codes",
4184
+ scenarioId: "generic-error",
4185
+ title: "An error code needs no invented payload",
4186
+ outcome: "no-match",
4187
+ files: [
4188
+ {
4189
+ path: "app/result.ts",
4190
+ source: "type Result<T, E> = { ok: true; value: T } | { ok: false; error: E }; export type Saved = Result<number, 'duplicate' | 'invalid_transition'>;"
4191
+ }
4192
+ ],
4193
+ focusPath: "app/result.ts",
4194
+ expectedCount: 0,
4195
+ public: true
4196
+ },
4197
+ {
4198
+ id: "producer-renders-context",
4199
+ scenarioId: "consumer-formatting",
4200
+ title: "A code alone does not move message formatting to the consumer",
4201
+ outcome: "match",
4202
+ files: [
4203
+ {
4204
+ path: "app/result.ts",
4205
+ source: "export function reject(name: string) { return { ok: false, code: 'duplicate', message: `Duplicate ${name}` }; }"
4206
+ }
4207
+ ],
4208
+ focusPath: "app/result.ts",
4209
+ expectedCount: 1,
4210
+ public: true
4211
+ },
4212
+ {
4213
+ id: "consumer-renders-context",
4214
+ scenarioId: "consumer-formatting",
4215
+ title: "Retain the typed context and format after handling the code",
4216
+ outcome: "no-match",
4217
+ files: [
4218
+ {
4219
+ path: "app/result.ts",
4220
+ source: "type Duplicate = { code: 'duplicate'; name: string }; export function reject(name: string): { ok: false; error: Duplicate } { return { ok: false, error: { code: 'duplicate', name } }; } export function format(error: Duplicate): string { return `Duplicate ${error.name}`; }"
4221
+ }
4222
+ ],
4223
+ focusPath: "app/result.ts",
4224
+ expectedCount: 0,
4225
+ public: true
4226
+ }
4227
+ ]
4228
+ };
4229
+
4119
4230
  // src/docs/prefer-constant-time-secret-compare.ts
4120
4231
  var PREFER_CONSTANT_TIME_SECRET_COMPARE_DOCUMENTATION = {
4121
4232
  summary: "Prefer a supported constant-time comparison primitive for secret-like values.",
@@ -6514,6 +6625,7 @@ var RULE_DOCUMENTATION = {
6514
6625
  "no-zod-native-enum": NO_ZOD_NATIVE_ENUM_DOCUMENTATION,
6515
6626
  "no-zod-parse-typed-object": NO_ZOD_PARSE_TYPED_OBJECT_DOCUMENTATION,
6516
6627
  "prefer-await-in-async-return": PREFER_AWAIT_IN_ASYNC_RETURN_DOCUMENTATION,
6628
+ "prefer-coded-error-result": PREFER_CODED_ERROR_RESULT_DOCUMENTATION,
6517
6629
  "prefer-constant-time-secret-compare": PREFER_CONSTANT_TIME_SECRET_COMPARE_DOCUMENTATION,
6518
6630
  "prefer-dependency-interface": PREFER_DEPENDENCY_INTERFACE_DOCUMENTATION,
6519
6631
  "prefer-discriminated-union": PREFER_DISCRIMINATED_UNION_DOCUMENTATION,