Skip to content

Commit bd9eca7

Browse files
committed
feat: add wrapResponseErrors option
1 parent 66fa86f commit bd9eca7

File tree

2 files changed

+53
-26
lines changed

2 files changed

+53
-26
lines changed

nodejs/src/error.ts

Lines changed: 14 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -18,11 +18,23 @@ class HttpResponseError extends HackMDError {
1818

1919
class MissingRequiredArgument extends HackMDError {}
2020
class InternalServerError extends HttpResponseError {}
21-
21+
class TooManyRequestsError extends HttpResponseError {
22+
public constructor (
23+
message: string,
24+
readonly code: number,
25+
readonly statusText: string,
26+
readonly userLimit: number,
27+
readonly userRemaining: number,
28+
readonly resetAfter?: number,
29+
) {
30+
super(message, code, statusText)
31+
}
32+
}
2233

2334
export {
2435
HackMDError,
2536
HttpResponseError,
2637
MissingRequiredArgument,
27-
InternalServerError
38+
InternalServerError,
39+
TooManyRequestsError,
2840
}

nodejs/src/index.ts

Lines changed: 39 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -12,10 +12,14 @@ const defaultOption: RequestOptions = {
1212

1313
type OptionReturnType<Opt, T> = Opt extends { unwrapData: false } ? AxiosResponse<T> : Opt extends { unwrapData: true } ? T : T
1414

15+
export type APIClientOptions = {
16+
wrapResponseErrors: boolean
17+
}
18+
1519
export class API {
1620
private axios: AxiosInstance
1721

18-
constructor (readonly accessToken: string, public hackmdAPIEndpointURL: string = "https://api.hackmd.io/v1") {
22+
constructor (readonly accessToken: string, public hackmdAPIEndpointURL: string = "https://api.hackmd.io/v1", public options: APIClientOptions = { wrapResponseErrors: true }) {
1923
if (!accessToken) {
2024
throw new HackMDErrors.MissingRequiredArgument('Missing access token when creating HackMD client')
2125
}
@@ -37,30 +41,41 @@ export class API {
3741
}
3842
)
3943

40-
this.axios.interceptors.response.use(
41-
(response: AxiosResponse) => {
42-
return response
43-
},
44-
async (err: AxiosError) => {
45-
if (!err.response) {
46-
return Promise.reject(err)
47-
}
48-
49-
if (err.response.status >= 500) {
50-
throw new HackMDErrors.InternalServerError(
51-
`HackMD internal error (${err.response.status} ${err.response.statusText})`,
52-
err.response.status,
53-
err.response.statusText,
54-
)
55-
} else {
56-
throw new HackMDErrors.HttpResponseError(
57-
`Received an error response (${err.response.status} ${err.response.statusText}) from HackMD`,
58-
err.response.status,
59-
err.response.statusText,
60-
)
44+
if (options.wrapResponseErrors) {
45+
this.axios.interceptors.response.use(
46+
(response: AxiosResponse) => {
47+
return response
48+
},
49+
async (err: AxiosError) => {
50+
if (!err.response) {
51+
return Promise.reject(err)
52+
}
53+
54+
if (err.response.status >= 500) {
55+
throw new HackMDErrors.InternalServerError(
56+
`HackMD internal error (${err.response.status} ${err.response.statusText})`,
57+
err.response.status,
58+
err.response.statusText,
59+
)
60+
} else if (err.response.status === 429) {
61+
throw new HackMDErrors.TooManyRequestsError(
62+
`Too many requests (${err.response.status} ${err.response.statusText})`,
63+
err.response.status,
64+
err.response.statusText,
65+
parseInt(err.response.headers['x-ratelimit-limit'], 10),
66+
parseInt(err.response.headers['x-ratelimit-remaining'], 10),
67+
parseInt(err.response.headers['x-ratelimit-userreset'], 10),
68+
)
69+
} else {
70+
throw new HackMDErrors.HttpResponseError(
71+
`Received an error response (${err.response.status} ${err.response.statusText}) from HackMD`,
72+
err.response.status,
73+
err.response.statusText,
74+
)
75+
}
6176
}
62-
}
63-
)
77+
)
78+
}
6479
}
6580

6681
async getMe<Opt extends RequestOptions> (options = defaultOption as Opt): Promise<OptionReturnType<Opt, GetMe>> {

0 commit comments

Comments
 (0)