Skip to content

Commit 8140a96

Browse files
committed
feat(api): Implement the /api/pages/:project/replace/links endpoint
1 parent ecc74fd commit 8140a96

File tree

5 files changed

+103
-0
lines changed

5 files changed

+103
-0
lines changed

api/pages/project.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -136,3 +136,4 @@ export async function* list(
136136
}
137137

138138
export * as title from "./project/title.ts";
139+
export * as replace from "./project/replace.ts";

api/pages/project/replace.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
export * as links from "./replace/links.ts";

api/pages/project/replace/links.ts

Lines changed: 85 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,85 @@
1+
import type {
2+
NotFoundError,
3+
NotLoggedInError,
4+
NotMemberError,
5+
} from "@cosense/types/rest";
6+
import type { ResponseOfEndpoint } from "../../../../targeted_response.ts";
7+
import { type ExtendedOptions, setDefaults } from "../../../../util.ts";
8+
import { cookie } from "../../../../rest/auth.ts";
9+
import { get } from "../../../users/me.ts";
10+
11+
/** Constructs a request for the `/api/pages/:project/replace/links` endpoint
12+
*
13+
* @param project - The project name where all links will be replaced
14+
* @param from - The original link text to be replaced
15+
* @param to - The new link text to replace with
16+
* @param init - Additional configuration options
17+
* @returns A {@linkcode Request} object for replacing links in `project`
18+
*/
19+
export const makePostRequest = <R extends Response | undefined>(
20+
project: string,
21+
from: string,
22+
to: string,
23+
init?: ExtendedOptions<R>,
24+
): Request => {
25+
const { sid, hostName, csrf } = setDefaults(init ?? {});
26+
27+
return new Request(
28+
`https://${hostName}/api/pages/${project}/replace/links`,
29+
{
30+
method: "POST",
31+
headers: {
32+
"Content-Type": "application/json;charset=utf-8",
33+
"X-CSRF-TOKEN": csrf ?? "",
34+
...(sid ? { Cookie: cookie(sid) } : {}),
35+
},
36+
body: JSON.stringify({ from, to }),
37+
},
38+
);
39+
};
40+
41+
/** Retrieves JSON data for a specified page
42+
*
43+
* @param project - The project name where all links will be replaced
44+
* @param from - The original link text to be replaced
45+
* @param to - The new link text to replace with
46+
* @param init - Additional configuration options
47+
* @returns A {@linkcode Result}<{@linkcode unknown}, {@linkcode Error}> containing:
48+
* - Success: The page data in JSON format
49+
* - Error: One of several possible errors:
50+
* - {@linkcode NotFoundError}: Page not found
51+
* - {@linkcode NotLoggedInError}: Authentication required
52+
* - {@linkcode NotMemberError}: User lacks access
53+
*/
54+
export const post = async <R extends Response | undefined = Response>(
55+
project: string,
56+
from: string,
57+
to: string,
58+
init?: ExtendedOptions<R>,
59+
): Promise<
60+
ResponseOfEndpoint<{
61+
200: string;
62+
404: NotFoundError;
63+
401: NotLoggedInError;
64+
403: NotMemberError;
65+
}, R>
66+
> => {
67+
let { csrf, fetch, ...init2 } = setDefaults(init ?? {});
68+
69+
if (!csrf) {
70+
const res = await get(init2);
71+
if (!res.ok) return res;
72+
csrf = (await res.json()).csrfToken;
73+
}
74+
75+
return fetch(
76+
makePostRequest(project, from, to, { csrf, ...init2 }),
77+
) as Promise<
78+
ResponseOfEndpoint<{
79+
200: string;
80+
404: NotFoundError;
81+
401: NotLoggedInError;
82+
403: NotMemberError;
83+
}, R>
84+
>;
85+
};

deno.jsonc

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,8 @@
2727
"./unstable-api/pages/project/title": "./api/pages/project/title.ts",
2828
"./unstable-api/pages/project/title/text": "./api/pages/project/title/text.ts",
2929
"./unstable-api/pages/project/title/icon": "./api/pages/project/title/icon.ts",
30+
"./unstable-api/pages/project/replace": "./api/pages/project/replace.ts",
31+
"./unstable-api/pages/project/replace/links": "./api/pages/project/replace/links.ts",
3032
"./unstable-api/users": "./api/users.ts",
3133
"./unstable-api/users/me": "./api/users/me.ts"
3234
},

util.ts

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -54,6 +54,20 @@ export interface OAuthOptions<R extends Response | undefined>
5454
accessToken: string;
5555
}
5656

57+
/** Extended options including CSRF token configuration
58+
*
59+
* Extends BaseOptions with CSRF token support for endpoints
60+
* that require CSRF protection.
61+
*/
62+
export interface ExtendedOptions<R extends Response | undefined>
63+
extends BaseOptions<R> {
64+
/** CSRF token
65+
*
66+
* If it isn't set, automatically get CSRF token from scrapbox.io server.
67+
*/
68+
csrf?: string;
69+
}
70+
5771
/** Set default values for {@linkcode BaseOptions}
5872
*
5973
* Ensures all required fields have appropriate default values while

0 commit comments

Comments
 (0)