2026-07-06 23:38:30 +08:00
|
|
|
|
import { readErrorBody, summarizeFormData } from "../utils/fetch";
|
2026-07-06 23:29:54 +08:00
|
|
|
|
|
2026-07-06 21:47:38 +08:00
|
|
|
|
/** Modrinth API v2 的基础请求客户端,封装鉴权与 User-Agent。 */
|
|
|
|
|
|
export class ModrinthClient {
|
|
|
|
|
|
private base = "https://api.modrinth.com/v2";
|
|
|
|
|
|
private token: string;
|
2026-07-06 23:13:17 +08:00
|
|
|
|
private userAgent?: string;
|
2026-07-06 21:47:38 +08:00
|
|
|
|
|
|
|
|
|
|
constructor(token: string, userAgent?: string) {
|
|
|
|
|
|
this.token = token;
|
2026-07-06 23:13:17 +08:00
|
|
|
|
this.userAgent = userAgent;
|
2026-07-06 21:47:38 +08:00
|
|
|
|
}
|
|
|
|
|
|
|
2026-07-06 23:13:17 +08:00
|
|
|
|
/** 构造通用请求头(Authorization,以及可选的 User-Agent)。 */
|
2026-07-06 21:47:38 +08:00
|
|
|
|
private headers(): Record<string, string> {
|
2026-07-06 23:13:17 +08:00
|
|
|
|
const h: Record<string, string> = {
|
2026-07-06 21:47:38 +08:00
|
|
|
|
Authorization: this.token,
|
|
|
|
|
|
};
|
2026-07-06 23:13:17 +08:00
|
|
|
|
if (this.userAgent) {
|
|
|
|
|
|
h["User-Agent"] = this.userAgent;
|
|
|
|
|
|
}
|
|
|
|
|
|
return h;
|
2026-07-06 21:47:38 +08:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/** 发送 GET 请求并解析 JSON 响应体。 */
|
|
|
|
|
|
async get<T>(path: string): Promise<T> {
|
|
|
|
|
|
const res = await fetch(`${this.base}${path}`, {
|
|
|
|
|
|
headers: this.headers(),
|
|
|
|
|
|
});
|
|
|
|
|
|
if (!res.ok) {
|
2026-07-06 23:29:54 +08:00
|
|
|
|
const body = await readErrorBody(res);
|
2026-07-06 21:47:38 +08:00
|
|
|
|
throw new Error(
|
2026-07-06 23:29:54 +08:00
|
|
|
|
`Modrinth API GET ${path} failed: ${res.status} ${res.statusText}\n${body}`,
|
2026-07-06 21:47:38 +08:00
|
|
|
|
);
|
|
|
|
|
|
}
|
|
|
|
|
|
return res.json() as Promise<T>;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
|
* 发送 POST 请求,body 为 FormData(multipart/form-data)。
|
|
|
|
|
|
* 不手动设置 Content-Type,让 fetch 自动生成含 boundary 的头。
|
|
|
|
|
|
*/
|
|
|
|
|
|
async post<T>(path: string, body: FormData): Promise<T> {
|
|
|
|
|
|
const res = await fetch(`${this.base}${path}`, {
|
|
|
|
|
|
method: "POST",
|
|
|
|
|
|
headers: this.headers(),
|
|
|
|
|
|
body,
|
|
|
|
|
|
});
|
|
|
|
|
|
if (!res.ok) {
|
2026-07-06 23:38:30 +08:00
|
|
|
|
const reqBody = summarizeFormData(body);
|
2026-07-06 23:29:54 +08:00
|
|
|
|
const resBody = await readErrorBody(res);
|
2026-07-06 21:47:38 +08:00
|
|
|
|
throw new Error(
|
2026-07-06 23:38:30 +08:00
|
|
|
|
`Modrinth API POST ${path} failed: ${res.status} ${res.statusText}\n\n--Request--:\n${reqBody}\n\n--Response--:\n${resBody}`,
|
2026-07-06 21:47:38 +08:00
|
|
|
|
);
|
|
|
|
|
|
}
|
|
|
|
|
|
return res.json() as Promise<T>;
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|