ModReleaser/src/lib/modrinth/client.ts

64 lines
1.9 KiB
TypeScript
Raw Normal View History

import { isPublishDryRun, interceptUpload } from "../utils/dryRun";
import { readErrorBody, summarizeFormData } from "../utils/fetch";
/** Modrinth API v2 的基础请求客户端,封装鉴权与 User-Agent。 */
export class ModrinthClient {
private base = "https://api.modrinth.com/v2";
private token: string;
private userAgent?: string;
constructor(token: string, userAgent?: string) {
this.token = token;
this.userAgent = userAgent;
}
/** 构造通用请求头Authorization以及可选的 User-Agent。 */
private headers(): Record<string, string> {
const h: Record<string, string> = {
Authorization: this.token,
};
if (this.userAgent) {
h["User-Agent"] = this.userAgent;
}
return h;
}
/** 发送 GET 请求并解析 JSON 响应体。 */
async get<T>(path: string): Promise<T> {
const res = await fetch(`${this.base}${path}`, {
headers: this.headers(),
});
if (!res.ok) {
const body = await readErrorBody(res);
throw new Error(
`Modrinth API GET ${path} failed: ${res.status} ${res.statusText}\n${body}`,
);
}
return res.json() as Promise<T>;
}
/**
* POST body FormDatamultipart/form-data
* Content-Type fetch boundary
*/
async post<T>(path: string, body: FormData): Promise<T> {
const url = `${this.base}${path}`;
if (isPublishDryRun()) {
return interceptUpload("Modrinth", "POST", url, body) as Promise<T>;
}
const res = await fetch(url, {
method: "POST",
headers: this.headers(),
body,
});
if (!res.ok) {
const reqBody = summarizeFormData(body);
const resBody = await readErrorBody(res);
throw new Error(
`Modrinth API POST ${path} failed: ${res.status} ${res.statusText}\n\n--Request--:\n${reqBody}\n\n--Response--:\n${resBody}`,
);
}
return res.json() as Promise<T>;
}
}