102 lines
3.1 KiB
TypeScript
102 lines
3.1 KiB
TypeScript
import axios, {
|
||
isAxiosError,
|
||
type AxiosRequestConfig,
|
||
type AxiosResponse,
|
||
} from "axios";
|
||
|
||
import { withAdminAuthHeader } from "@/lib/admin-auth";
|
||
import { withAdminLocaleHeaders } from "@/lib/admin-locale";
|
||
import { LotteryApiBizError, LotteryApiEnvelopeError } from "@/types/api/errors";
|
||
import { isApiEnvelope } from "@/types/api/envelope";
|
||
|
||
const baseURL = process.env.NEXT_PUBLIC_LOTTERY_API_BASE_URL?.trim();
|
||
|
||
/** 是否已配置后台 API 根地址(客户端/服务端均可用 `NEXT_PUBLIC_*`) */
|
||
export function hasLotteryAdminApiBaseUrl(): boolean {
|
||
return baseURL !== undefined && baseURL !== "";
|
||
}
|
||
|
||
export const adminHttp = axios.create({
|
||
baseURL: baseURL && baseURL !== "" ? baseURL : undefined,
|
||
timeout: 30_000,
|
||
headers: { Accept: "application/json" },
|
||
});
|
||
|
||
export function unwrapData<T>(payload: unknown): T {
|
||
if (!isApiEnvelope(payload)) {
|
||
throw new LotteryApiEnvelopeError();
|
||
}
|
||
if (payload.code !== 0) {
|
||
throw new LotteryApiBizError(payload.msg, payload.code, payload.data);
|
||
}
|
||
return payload.data as T;
|
||
}
|
||
|
||
export function unwrapResponse<T>(res: AxiosResponse<unknown>): T {
|
||
return unwrapData<T>(res.data);
|
||
}
|
||
|
||
/** 登录/验证码等:**不**附加 `Authorization`。 */
|
||
export async function publicAdminRequest<T>(
|
||
config: AxiosRequestConfig,
|
||
): Promise<T> {
|
||
try {
|
||
const res = await adminHttp.request<unknown>(
|
||
withAdminLocaleHeaders(config),
|
||
);
|
||
return unwrapResponse<T>(res);
|
||
} catch (err: unknown) {
|
||
if (isAxiosError(err) && err.response?.data !== undefined) {
|
||
const body = err.response.data;
|
||
if (isApiEnvelope(body) && body.code !== 0) {
|
||
throw new LotteryApiBizError(body.msg, body.code, body.data);
|
||
}
|
||
}
|
||
throw err;
|
||
}
|
||
}
|
||
|
||
export async function request<T>(config: AxiosRequestConfig): Promise<T> {
|
||
const merged = withAdminAuthHeader(withAdminLocaleHeaders(config));
|
||
try {
|
||
const res = await adminHttp.request<unknown>(merged);
|
||
return unwrapResponse<T>(res);
|
||
} catch (err: unknown) {
|
||
if (isAxiosError(err) && err.response?.data !== undefined) {
|
||
const body = err.response.data;
|
||
if (isApiEnvelope(body) && body.code !== 0) {
|
||
throw new LotteryApiBizError(body.msg, body.code, body.data);
|
||
}
|
||
}
|
||
throw err;
|
||
}
|
||
}
|
||
|
||
export const adminRequest = {
|
||
request,
|
||
|
||
get: <T>(url: string, config?: Omit<AxiosRequestConfig, "url" | "method">) =>
|
||
request<T>({ ...config, url, method: "GET" }),
|
||
|
||
delete: <T>(url: string, config?: Omit<AxiosRequestConfig, "url" | "method">) =>
|
||
request<T>({ ...config, url, method: "DELETE" }),
|
||
|
||
post: <T>(
|
||
url: string,
|
||
data?: unknown,
|
||
config?: Omit<AxiosRequestConfig, "url" | "method" | "data">,
|
||
) => request<T>({ ...config, url, method: "POST", data }),
|
||
|
||
patch: <T>(
|
||
url: string,
|
||
data?: unknown,
|
||
config?: Omit<AxiosRequestConfig, "url" | "method" | "data">,
|
||
) => request<T>({ ...config, url, method: "PATCH", data }),
|
||
|
||
put: <T>(
|
||
url: string,
|
||
data?: unknown,
|
||
config?: Omit<AxiosRequestConfig, "url" | "method" | "data">,
|
||
) => request<T>({ ...config, url, method: "PUT", data }),
|
||
};
|