Skip to content

Commit ed57c55

Browse files
committed
feat(api): Enhance error handling in listPages function and introduce TypedError interface
1 parent a37eb3a commit ed57c55

File tree

2 files changed

+66
-7
lines changed

2 files changed

+66
-7
lines changed

api/pages/project.ts

+20-7
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,12 @@ import type {
88
import { type BaseOptions, setDefaults } from "../../util.ts";
99
import { cookie } from "../../rest/auth.ts";
1010
import type { ResponseOfEndpoint } from "../../targeted_response.ts";
11+
import {
12+
type HTTPError,
13+
makeError,
14+
makeHTTPError,
15+
type TypedError,
16+
} from "../../error.ts";
1117

1218
/** Options for {@linkcode listPages} */
1319
export interface ListPagesOption<R extends Response | undefined>
@@ -99,7 +105,7 @@ export const get = <R extends Response | undefined = Response>(
99105
*
100106
* @param project The project name to list pages from
101107
* @param options Configuration options for pagination and sorting
102-
* @throws {HTTPError} If any requests in the pagination sequence fail
108+
* @throws {HTTPError | TypedError<"NotLoggedInError" | "NotMemberError" | "NotFoundError">} If any requests in the pagination sequence fail
103109
*/
104110
export async function* list(
105111
project: string,
@@ -108,8 +114,19 @@ export async function* list(
108114
const props = { ...(options ?? {}), skip: options?.skip ?? 0 };
109115
while (true) {
110116
const response = await get(project, props);
111-
if (response.status !== 200) {
112-
throw new Error(response.statusText, { cause: response }) as HTTPError;
117+
switch (response.status) {
118+
case 200:
119+
break;
120+
case 401:
121+
case 403:
122+
case 404: {
123+
const error = await response.json();
124+
throw makeError(error.name, error.message) satisfies TypedError<
125+
"NotLoggedInError" | "NotMemberError" | "NotFoundError"
126+
>;
127+
}
128+
default:
129+
throw makeHTTPError(response) satisfies HTTPError;
113130
}
114131
const list = await response.json();
115132
yield* list.pages;
@@ -119,7 +136,3 @@ export async function* list(
119136
}
120137

121138
export * as title from "./project/title.ts";
122-
123-
export interface HTTPError extends Error {
124-
readonly cause: Response;
125-
}

error.ts

+46
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,46 @@
1+
export interface TypedError<Name extends string, Cause extends Error = Error>
2+
extends Error {
3+
/**
4+
* The error name
5+
*/
6+
readonly name: Name;
7+
8+
/**
9+
* The error cause
10+
*/
11+
readonly cause?: Cause;
12+
}
13+
14+
export const makeError = <Name extends string, Cause extends Error = Error>(
15+
name: Name,
16+
message?: string,
17+
cause?: Cause,
18+
): TypedError<Name, Cause> => {
19+
// from https://stackoverflow.com/a/43001581
20+
type Writeable<T> = { -readonly [P in keyof T]: T[P] };
21+
22+
const error = new Error(message, { cause }) as Writeable<
23+
TypedError<Name, Cause>
24+
>;
25+
error.name = name;
26+
return error;
27+
};
28+
29+
export interface HTTPError<Cause extends Error = Error>
30+
extends TypedError<"HTTPError", Cause> {
31+
readonly response: Response;
32+
}
33+
34+
export const makeHTTPError = <Cause extends Error = Error>(
35+
response: Response,
36+
message?: string,
37+
cause?: Cause,
38+
): HTTPError<Cause> => {
39+
// from https://stackoverflow.com/a/43001581
40+
type Writeable<T> = { -readonly [P in keyof T]: T[P] };
41+
42+
const error = new Error(message, { cause }) as Writeable<HTTPError<Cause>>;
43+
error.name = "HTTPError";
44+
error.response = response;
45+
return error;
46+
};

0 commit comments

Comments
 (0)