errors: add ConsumedResponse type + use for ResponseError

Signed-off-by: Patrik Oldsberg <poldsberg@gmail.com>
This commit is contained in:
Patrik Oldsberg
2022-06-23 11:13:21 +02:00
parent 7510cab5bb
commit 6d61b44466
6 changed files with 67 additions and 7 deletions
+7
View File
@@ -0,0 +1,7 @@
---
'@backstage/errors': minor
---
The `ResponseError.fromResponse` now accepts a more narrow response type, in order to avoid incompatibilities between different fetch implementations.
The `response` property of `ResponseError` has also been narrowed to a new `ConsumedResponse` type that omits all the properties for consuming the body of the response. This is not considered a breaking change as it was always an error to try to consume the body of the response.
+20 -3
View File
@@ -14,6 +14,17 @@ export class AuthenticationError extends CustomErrorBase {}
// @public
export class ConflictError extends CustomErrorBase {}
// @public
export type ConsumedResponse = {
readonly headers: Headers;
readonly ok: boolean;
readonly redirected: boolean;
readonly status: number;
readonly statusText: string;
readonly type: ResponseType;
readonly url: string;
};
// @public
export class CustomErrorBase extends Error {
constructor(message?: string, cause?: Error | unknown);
@@ -67,15 +78,21 @@ export class NotModifiedError extends CustomErrorBase {}
// @public
export function parseErrorResponseBody(
response: Response,
response: ConsumedResponse & {
text(): Promise<string>;
},
): Promise<ErrorResponseBody>;
// @public
export class ResponseError extends Error {
readonly body: ErrorResponseBody;
readonly cause: Error;
static fromResponse(response: Response): Promise<ResponseError>;
readonly response: Response;
static fromResponse(
response: ConsumedResponse & {
text(): Promise<string>;
},
): Promise<ResponseError>;
readonly response: ConsumedResponse;
}
// @public
+6 -3
View File
@@ -19,6 +19,7 @@ import {
ErrorResponseBody,
parseErrorResponseBody,
} from '../serialization/response';
import { ConsumedResponse } from './types';
/**
* An error thrown as the result of a failed server request.
@@ -34,7 +35,7 @@ export class ResponseError extends Error {
* Note that the body of this response is always consumed. Its parsed form is
* in the `body` field.
*/
readonly response: Response;
readonly response: ConsumedResponse;
/**
* The parsed JSON error body, as sent by the server.
@@ -59,7 +60,9 @@ export class ResponseError extends Error {
* function consumes the body of the response, and assumes that it hasn't
* been consumed before.
*/
static async fromResponse(response: Response): Promise<ResponseError> {
static async fromResponse(
response: ConsumedResponse & { text(): Promise<string> },
): Promise<ResponseError> {
const data = await parseErrorResponseBody(response);
const status = data.response.statusCode || response.status;
@@ -77,7 +80,7 @@ export class ResponseError extends Error {
private constructor(props: {
message: string;
response: Response;
response: ConsumedResponse;
data: ErrorResponseBody;
cause: Error;
}) {
+1
View File
@@ -27,3 +27,4 @@ export {
} from './common';
export { CustomErrorBase } from './CustomErrorBase';
export { ResponseError } from './ResponseError';
export type { ConsumedResponse } from './types';
+31
View File
@@ -0,0 +1,31 @@
/*
* Copyright 2022 The Backstage Authors
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
/**
* ConsumedResponse represents a Response that is known to have been consumed.
* The methods and properties used to read the body contents are therefore omitted.
*
* @public
*/
export type ConsumedResponse = {
readonly headers: Headers;
readonly ok: boolean;
readonly redirected: boolean;
readonly status: number;
readonly statusText: string;
readonly type: ResponseType;
readonly url: string;
};
@@ -14,6 +14,7 @@
* limitations under the License.
*/
import { ConsumedResponse } from '../errors/types';
import { SerializedError } from './error';
/**
@@ -53,7 +54,7 @@ export type ErrorResponseBody = {
* @param response - The response of a failed request
*/
export async function parseErrorResponseBody(
response: Response,
response: ConsumedResponse & { text(): Promise<string> },
): Promise<ErrorResponseBody> {
try {
const text = await response.text();