• Home
  • Features
  • Pricing
  • Docs
  • Announcements
  • Sign In

endatix / endatix-hub / 25332345966

04 May 2026 05:09PM UTC coverage: 51.661% (-0.5%) from 52.111%
25332345966

push

github

web-flow
feat: Data Lists  (#590)

1046 of 1768 branches covered (59.16%)

Branch coverage included in aggregate %.

325 of 704 new or added lines in 43 files covered. (46.16%)

5 existing lines in 4 files now uncovered.

4258 of 8499 relevant lines covered (50.1%)

9.35 hits per line

Source File
Press 'n' to go to next uncovered line, 'b' for previous

56.0
/lib/endatix-api/shared/http-error-mapper.ts
1
import { ApiErrorDetails, ApiResult } from "./api-result";
2
import {
3
  ERROR_CODE,
4
  getErrorMessageWithFallback,
5
  type ErrorCode,
6
} from "./error-codes";
7
import { parseErrorResponse } from "./problem-details";
8

9
/**
10
 * Maps a non-OK fetch Response to an ApiResult error using shared problem-details parsing
11
 * and consistent status -> ApiErrorType mapping. Used by both the Node-side EndatixApi and
12
 * browser-side public clients to keep error semantics in lock-step.
13
 */
14
export async function mapResponseToApiError<T>(
15
  response: Response,
16
  details: ApiErrorDetails,
17
): Promise<ApiResult<T>> {
18
  const problemDetails = await parseErrorResponse(response).catch(() => null);
4✔
19

20
  const serverErrorCode = problemDetails?.errorCode as ErrorCode | undefined;
4✔
21

22
  // Match the original Node contract: only consult the friendly canned message
23
  // when the SERVER provided an errorCode. Otherwise prefer raw detail/title and
24
  // fall through to DEFAULT_ERROR_MESSAGE so we don't replace diagnostic detail
25
  // with a generic, status-inferred string.
26
  const message = getErrorMessageWithFallback(
4✔
27
    serverErrorCode,
28
    problemDetails?.detail ?? problemDetails?.title,
29
  );
30

31
  // The errorCode stored on the ApiResult still reflects the server code when
32
  // available, otherwise the factory's status-derived default takes over.
33
  const errorCode =
34
    serverErrorCode ?? inferErrorCodeFromStatus(response.status);
4✔
35

36
  const enrichedDetails: ApiErrorDetails = {
4✔
37
    ...details,
38
    statusCode: details.statusCode ?? response.status,
39
    details: problemDetails?.detail ?? details.details,
40
  };
41

42
  switch (response.status) {
4✔
43
    case 400:
44
      return ApiResult.validationError(
3✔
45
        message,
46
        errorCode,
47
        enrichedDetails,
48
        problemDetails?.fields,
49
      );
50
    case 401:
NEW
51
      return ApiResult.authError(message, errorCode, enrichedDetails);
×
52
    case 403:
NEW
53
      return ApiResult.forbiddenError(message, errorCode, enrichedDetails);
×
54
    case 404:
NEW
55
      return ApiResult.notFoundError(message, enrichedDetails);
×
56
    case 429: {
NEW
57
      const retryAfter = response.headers.get("Retry-After");
×
NEW
58
      return ApiResult.rateLimitError(message, {
×
59
        ...enrichedDetails,
60
        retryAfter: retryAfter ? Number.parseInt(retryAfter, 10) : undefined,
61
      });
62
    }
63
    case 500:
64
    case 502:
65
    case 503:
66
    case 504:
67
      return ApiResult.serverError(message, enrichedDetails);
1✔
68
    default:
NEW
69
      return ApiResult.unknownError(message, enrichedDetails);
×
70
  }
71
}
72

73
function inferErrorCodeFromStatus(status: number): ErrorCode | undefined {
74
  switch (status) {
3✔
75
    case 400:
76
      return ERROR_CODE.VALIDATION_ERROR;
2✔
77
    case 401:
NEW
78
      return ERROR_CODE.AUTHENTICATION_REQUIRED;
×
79
    case 403:
NEW
80
      return ERROR_CODE.ACCESS_FORBIDDEN;
×
81
    case 404:
NEW
82
      return ERROR_CODE.RESOURCE_NOT_FOUND;
×
83
    case 429:
NEW
84
      return ERROR_CODE.RATE_LIMIT_EXCEEDED;
×
85
    case 500:
86
    case 502:
87
    case 503:
88
    case 504:
89
      return ERROR_CODE.SERVER_ERROR;
1✔
90
    default:
NEW
91
      return undefined;
×
92
  }
93
}
STATUS · Troubleshooting · Open an Issue · Sales · Support · CAREERS · ENTERPRISE · START FREE · SCHEDULE DEMO
ANNOUNCEMENTS · TWITTER · TOS & SLA · Supported CI Services · What's a CI service? · Automated Testing

© 2026 Coveralls, Inc