Skip to content

Commit fed3e94

Browse files
committed
✨ extract request builder and response analyzer in getPage/listPages and getProject/listProjects
1 parent 06350f3 commit fed3e94

File tree

6 files changed

+305
-69
lines changed

6 files changed

+305
-69
lines changed

rest/__snapshots__/pages.test.ts.snap

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
export const snapshot = {};
2+
3+
snapshot[`getPage 1`] = `
4+
Request {
5+
bodyUsed: false,
6+
headers: Headers {},
7+
method: "GET",
8+
redirect: "follow",
9+
url: "https://scrapbox.io/api/pages/takker/%E3%83%86%E3%82%B9%E3%83%88%E3%83%9A%E3%83%BC%E3%82%B8?followRe..."
10+
}
11+
`;
12+
13+
snapshot[`listPages 1`] = `
14+
Request {
15+
bodyUsed: false,
16+
headers: Headers {},
17+
method: "GET",
18+
redirect: "follow",
19+
url: "https://scrapbox.io/api/pages/takker?sort=updated"
20+
}
21+
`;
Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
export const snapshot = {};
2+
3+
snapshot[`getProject 1`] = `
4+
Request {
5+
bodyUsed: false,
6+
headers: Headers {},
7+
method: "GET",
8+
redirect: "follow",
9+
url: "https://scrapbox.io/api/projects/takker"
10+
}
11+
`;
12+
13+
snapshot[`listProjects 1`] = `
14+
Request {
15+
bodyUsed: false,
16+
headers: Headers {},
17+
method: "GET",
18+
redirect: "follow",
19+
url: "https://scrapbox.io/api/projects?ids=dummy-id1&ids=dummy-id2"
20+
}
21+
`;

rest/pages.test.ts

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
import { getPage, listPages } from "./pages.ts";
2+
import { assertSnapshot } from "../deps/testing.ts";
3+
4+
Deno.test("getPage", async (t) => {
5+
await assertSnapshot(
6+
t,
7+
getPage.toRequest("takker", "テストページ", { followRename: true }),
8+
);
9+
});
10+
Deno.test("listPages", async (t) => {
11+
await assertSnapshot(
12+
t,
13+
listPages.toRequest("takker", { sort: "updated" }),
14+
);
15+
});

rest/pages.ts

Lines changed: 127 additions & 40 deletions
Original file line numberDiff line numberDiff line change
@@ -14,37 +14,84 @@ import { BaseOptions, Result, setDefaults } from "./util.ts";
1414
export interface GetPageOption extends BaseOptions {
1515
/** use `followRename` */ followRename?: boolean;
1616
}
17-
/** 指定したページのJSONデータを取得する
18-
*
19-
* @param project 取得したいページのproject名
20-
* @param title 取得したいページのtitle 大文字小文字は問わない
21-
* @param options オプション
22-
*/
23-
export const getPage = async (
24-
project: string,
25-
title: string,
26-
options?: GetPageOption,
27-
): Promise<
28-
Result<
29-
Page,
30-
NotFoundError | NotLoggedInError | NotMemberError
31-
>
32-
> => {
33-
const { sid, hostName, fetch, followRename } = setDefaults(options ?? {});
34-
const req = new Request(
35-
`https://${hostName}/api/pages/${project}/${
36-
encodeTitleURI(title)
37-
}?followRename=${followRename ?? true}`,
17+
18+
const getPage_toRequest: GetPage["toRequest"] = (
19+
project,
20+
title,
21+
options,
22+
) => {
23+
const { sid, hostName, followRename } = setDefaults(options ?? {});
24+
const path = `https://${hostName}/api/pages/${project}/${
25+
encodeTitleURI(title)
26+
}?followRename=${followRename ?? true}`;
27+
return new Request(
28+
path,
3829
sid ? { headers: { Cookie: cookie(sid) } } : undefined,
3930
);
40-
const res = await fetch(req);
31+
};
32+
33+
const getPage_fromResponse: GetPage["fromResponse"] = async (res) => {
4134
if (!res.ok) {
4235
return makeError<NotFoundError | NotLoggedInError | NotMemberError>(res);
4336
}
4437
const value = (await res.json()) as Page;
4538
return { ok: true, value };
4639
};
4740

41+
export interface GetPage {
42+
/** /api/pages/:project/:title の要求を組み立てる
43+
*
44+
* @param project 取得したいページのproject名
45+
* @param title 取得したいページのtitle 大文字小文字は問わない
46+
* @param options オプション
47+
* @return request
48+
*/
49+
toRequest: (
50+
project: string,
51+
title: string,
52+
options?: GetPageOption,
53+
) => Request;
54+
55+
/** 帰ってきた応答からページのJSONデータを取得する
56+
*
57+
* @param res 応答
58+
* @return ページのJSONデータ
59+
*/
60+
fromResponse: (res: Response) => Promise<
61+
Result<
62+
Page,
63+
NotFoundError | NotLoggedInError | NotMemberError
64+
>
65+
>;
66+
67+
(project: string, title: string, options?: GetPageOption): Promise<
68+
Result<
69+
Page,
70+
NotFoundError | NotLoggedInError | NotMemberError
71+
>
72+
>;
73+
}
74+
75+
/** 指定したページのJSONデータを取得する
76+
*
77+
* @param project 取得したいページのproject名
78+
* @param title 取得したいページのtitle 大文字小文字は問わない
79+
* @param options オプション
80+
*/
81+
export const getPage: GetPage = async (
82+
project,
83+
title,
84+
options,
85+
) => {
86+
const { fetch } = setDefaults(options ?? {});
87+
const req = getPage_toRequest(project, title, options);
88+
const res = await fetch(req);
89+
return await getPage_fromResponse(res);
90+
};
91+
92+
getPage.toRequest = getPage_toRequest;
93+
getPage.fromResponse = getPage_fromResponse;
94+
4895
/** Options for `listPages()` */
4996
export interface ListPagesOption extends BaseOptions {
5097
/** the sort of page list to return
@@ -71,36 +118,76 @@ export interface ListPagesOption extends BaseOptions {
71118
*/
72119
limit?: number;
73120
}
74-
/** 指定したprojectのページを一覧する
75-
*
76-
* @param project 一覧したいproject
77-
* @param options オプション 取得範囲や並び順を決める
78-
*/
79-
export const listPages = async (
80-
project: string,
81-
options?: ListPagesOption,
82-
): Promise<
83-
Result<
84-
PageList,
85-
NotFoundError | NotLoggedInError | NotMemberError
86-
>
87-
> => {
88-
const { sid, hostName, fetch, sort, limit, skip } = setDefaults(
121+
122+
export interface ListPages {
123+
/** /api/pages/:project の要求を組み立てる
124+
*
125+
* @param project 取得したいページのproject名
126+
* @param options オプション
127+
* @return request
128+
*/
129+
toRequest: (
130+
project: string,
131+
options?: ListPagesOption,
132+
) => Request;
133+
134+
/** 帰ってきた応答からページのJSONデータを取得する
135+
*
136+
* @param res 応答
137+
* @return ページのJSONデータ
138+
*/
139+
fromResponse: (res: Response) => Promise<
140+
Result<
141+
PageList,
142+
NotFoundError | NotLoggedInError | NotMemberError
143+
>
144+
>;
145+
146+
(project: string, options?: ListPagesOption): Promise<
147+
Result<
148+
PageList,
149+
NotFoundError | NotLoggedInError | NotMemberError
150+
>
151+
>;
152+
}
153+
154+
const listPages_toRequest: ListPages["toRequest"] = (project, options) => {
155+
const { sid, hostName, sort, limit, skip } = setDefaults(
89156
options ?? {},
90157
);
91158
const params = new URLSearchParams();
92159
if (sort !== undefined) params.append("sort", sort);
93160
if (limit !== undefined) params.append("limit", `${limit}`);
94161
if (skip !== undefined) params.append("skip", `${skip}`);
95-
const req = new Request(
96-
`https://${hostName}/api/pages/${project}?${params.toString()}`,
162+
const path = `https://${hostName}/api/pages/${project}?${params.toString()}`;
163+
164+
return new Request(
165+
path,
97166
sid ? { headers: { Cookie: cookie(sid) } } : undefined,
98167
);
168+
};
99169

100-
const res = await fetch(req);
170+
const listPages_fromResponse: ListPages["fromResponse"] = async (res) => {
101171
if (!res.ok) {
102172
return makeError<NotFoundError | NotLoggedInError | NotMemberError>(res);
103173
}
104174
const value = (await res.json()) as PageList;
105175
return { ok: true, value };
106176
};
177+
178+
/** 指定したprojectのページを一覧する
179+
*
180+
* @param project 一覧したいproject
181+
* @param options オプション 取得範囲や並び順を決める
182+
*/
183+
export const listPages: ListPages = async (
184+
project,
185+
options?,
186+
) => {
187+
const { fetch } = setDefaults(options ?? {});
188+
const res = await fetch(listPages_toRequest(project, options));
189+
return await listPages_fromResponse(res);
190+
};
191+
192+
listPages.toRequest = listPages_toRequest;
193+
listPages.fromResponse = listPages_fromResponse;

rest/project.test.ts

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
import { getProject, listProjects } from "./project.ts";
2+
import { assertSnapshot } from "../deps/testing.ts";
3+
4+
Deno.test("getProject", async (t) => {
5+
await assertSnapshot(
6+
t,
7+
getProject.toRequest("takker"),
8+
);
9+
});
10+
Deno.test("listProjects", async (t) => {
11+
await assertSnapshot(
12+
t,
13+
listProjects.toRequest(["dummy-id1", "dummy-id2"]),
14+
);
15+
});

0 commit comments

Comments
 (0)