Skip to content

Commit 2fda9dd

Browse files
committed
breaking?
1 parent 4767529 commit 2fda9dd

File tree

1 file changed

+105
-99
lines changed

1 file changed

+105
-99
lines changed

Diff for: src/fetch-wrapper.ts

+105-99
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@ import { isPlainObject } from "./is-plain-object.js";
22
import { RequestError } from "@octokit/request-error";
33
import type { EndpointInterface } from "@octokit/types";
44

5-
export default function fetchWrapper(
5+
export default async function fetchWrapper(
66
requestOptions: ReturnType<EndpointInterface>,
77
) {
88
const fetch: typeof globalThis.fetch =
@@ -34,121 +34,127 @@ export default function fetchWrapper(
3434
let status: number;
3535
let url: string;
3636

37-
return fetch(requestOptions.url, {
38-
method: requestOptions.method,
39-
body,
40-
redirect: requestOptions.request?.redirect,
41-
// Header values must be `string`
42-
headers: requestHeaders,
43-
signal: requestOptions.request?.signal,
44-
// duplex must be set if request.body is ReadableStream or Async Iterables.
45-
// See https://fetch.spec.whatwg.org/#dom-requestinit-duplex.
46-
...(requestOptions.body && { duplex: "half" }),
47-
})
48-
.then(async (response) => {
49-
url = response.url;
50-
status = response.status;
51-
52-
for (const keyAndValue of response.headers) {
53-
responseHeaders[keyAndValue[0]] = keyAndValue[1];
54-
}
37+
let response: Response;
38+
39+
try {
40+
response = await fetch(requestOptions.url, {
41+
method: requestOptions.method,
42+
body,
43+
redirect: requestOptions.request?.redirect,
44+
// Header values must be `string`
45+
headers: requestHeaders,
46+
signal: requestOptions.request?.signal,
47+
// duplex must be set if request.body is ReadableStream or Async Iterables.
48+
// See https://fetch.spec.whatwg.org/#dom-requestinit-duplex.
49+
...(requestOptions.body && { duplex: "half" }),
50+
});
51+
// wrap fetch errors as RequestError if it is not a AbortError
52+
} catch (error) {
53+
let message = "Unknown Error";
54+
if (error instanceof Error) {
55+
if (error.name === "AbortError") throw error;
5556

56-
if ("deprecation" in responseHeaders) {
57-
const matches =
58-
responseHeaders.link &&
59-
responseHeaders.link.match(/<([^>]+)>; rel="deprecation"/);
60-
const deprecationLink = matches && matches.pop();
61-
log.warn(
62-
`[@octokit/request] "${requestOptions.method} ${
63-
requestOptions.url
64-
}" is deprecated. It is scheduled to be removed on ${responseHeaders.sunset}${
65-
deprecationLink ? `. See ${deprecationLink}` : ""
66-
}`,
67-
);
68-
}
57+
message = error.message;
6958

70-
if (status === 204 || status === 205) {
71-
return;
59+
// undici throws a TypeError for network errors
60+
// and puts the error message in `error.cause`
61+
// https://github.com/nodejs/undici/blob/e5c9d703e63cd5ad691b8ce26e3f9a81c598f2e3/lib/fetch/index.js#L227
62+
if (error.name === "TypeError" && "cause" in error) {
63+
if (error.cause instanceof Error) {
64+
message = error.cause.message;
65+
} else if (typeof error.cause === "string") {
66+
message = error.cause;
67+
}
7268
}
69+
}
7370

74-
// GitHub API returns 200 for HEAD requests
75-
if (requestOptions.method === "HEAD") {
76-
if (status < 400) {
77-
return;
78-
}
71+
const requestError = new RequestError(message, 500, {
72+
request: requestOptions,
73+
});
74+
requestError.cause = error;
7975

80-
throw new RequestError(response.statusText, status, {
81-
response: {
82-
url,
83-
status,
84-
headers: responseHeaders,
85-
data: undefined,
86-
},
87-
request: requestOptions,
88-
});
89-
}
76+
throw requestError;
77+
}
78+
url = response.url;
79+
status = response.status;
9080

91-
if (status === 304) {
92-
throw new RequestError("Not modified", status, {
93-
response: {
94-
url,
95-
status,
96-
headers: responseHeaders,
97-
data: await getResponseData(response),
98-
},
99-
request: requestOptions,
100-
});
101-
}
81+
for (const keyAndValue of response.headers) {
82+
responseHeaders[keyAndValue[0]] = keyAndValue[1];
83+
}
10284

103-
if (status >= 400) {
104-
const data = await getResponseData(response);
85+
if ("deprecation" in responseHeaders) {
86+
const matches =
87+
responseHeaders.link &&
88+
responseHeaders.link.match(/<([^>]+)>; rel="deprecation"/);
89+
const deprecationLink = matches && matches.pop();
90+
log.warn(
91+
`[@octokit/request] "${requestOptions.method} ${
92+
requestOptions.url
93+
}" is deprecated. It is scheduled to be removed on ${responseHeaders.sunset}${
94+
deprecationLink ? `. See ${deprecationLink}` : ""
95+
}`,
96+
);
97+
}
98+
99+
if (status === 204 || status === 205) {
100+
return;
101+
}
105102

106-
const error = new RequestError(toErrorMessage(data), status, {
107-
response: {
108-
url,
109-
status,
110-
headers: responseHeaders,
111-
data,
112-
},
113-
request: requestOptions,
114-
});
103+
// GitHub API returns 200 for HEAD requests
104+
if (requestOptions.method === "HEAD") {
105+
if (status < 400) {
106+
return;
107+
}
115108

116-
throw error;
117-
}
109+
throw new RequestError(response.statusText, status, {
110+
response: {
111+
url,
112+
status,
113+
headers: responseHeaders,
114+
data: undefined,
115+
},
116+
request: requestOptions,
117+
});
118+
}
118119

119-
return parseSuccessResponseBody
120-
? await getResponseData(response)
121-
: response.body;
122-
})
123-
.then((data) => {
124-
return {
120+
if (status === 304) {
121+
throw new RequestError("Not modified", status, {
122+
response: {
123+
url,
125124
status,
125+
headers: responseHeaders,
126+
data: await getResponseData(response),
127+
},
128+
request: requestOptions,
129+
});
130+
}
131+
132+
if (status >= 400) {
133+
const data = await getResponseData(response);
134+
135+
const error = new RequestError(toErrorMessage(data), status, {
136+
response: {
126137
url,
138+
status,
127139
headers: responseHeaders,
128140
data,
129-
};
130-
})
131-
.catch((error) => {
132-
if (error instanceof RequestError) throw error;
133-
else if (error.name === "AbortError") throw error;
141+
},
142+
request: requestOptions,
143+
});
134144

135-
let message = error.message;
145+
throw error;
146+
}
136147

137-
// undici throws a TypeError for network errors
138-
// and puts the error message in `error.cause`
139-
// https://github.com/nodejs/undici/blob/e5c9d703e63cd5ad691b8ce26e3f9a81c598f2e3/lib/fetch/index.js#L227
140-
if (error.name === "TypeError" && "cause" in error) {
141-
if (error.cause instanceof Error) {
142-
message = error.cause.message;
143-
} else if (typeof error.cause === "string") {
144-
message = error.cause;
145-
}
146-
}
148+
const responseBody = parseSuccessResponseBody
149+
? await getResponseData(response)
150+
: response.body;
147151

148-
throw new RequestError(message, 500, {
149-
request: requestOptions,
150-
});
151-
});
152+
return {
153+
status,
154+
url,
155+
headers: responseHeaders,
156+
data: responseBody,
157+
};
152158
}
153159

154160
async function getResponseData(response: Response) {

0 commit comments

Comments
 (0)