|
@@ -1,35 +1,42 @@
|
|
|
|
|
|
|
|
-import axios, { AxiosInstance } from 'axios';
|
|
|
|
|
-import { TikHubConfig, TikHubResponse } from './types.ts';
|
|
|
|
|
|
|
+import { TikHubConfig } from './types.ts';
|
|
|
|
|
|
|
|
/**
|
|
/**
|
|
|
* TikHub 客户端
|
|
* TikHub 客户端
|
|
|
* 直接调用 api.tikhub.io 的 API
|
|
* 直接调用 api.tikhub.io 的 API
|
|
|
|
|
+ * 使用原生 fetch 替代 axios
|
|
|
*/
|
|
*/
|
|
|
export class TikHubClient {
|
|
export class TikHubClient {
|
|
|
- private axiosInstance: AxiosInstance;
|
|
|
|
|
- private readonly BASE_URL = 'https://api.tikhub.io/api/v1';
|
|
|
|
|
- private readonly API_KEY = 'tKIbAsEM8X+GmE2vHqGW7D/ICwK1Q5V4viKFrWiPB6HholGdLFqZJmmyNw==';
|
|
|
|
|
|
|
+ private readonly baseURL: string;
|
|
|
|
|
+ private readonly apiKey: string;
|
|
|
|
|
+ private readonly headers: Record<string, string>;
|
|
|
|
|
|
|
|
constructor(config?: Partial<TikHubConfig>) {
|
|
constructor(config?: Partial<TikHubConfig>) {
|
|
|
// 允许通过配置覆盖默认 Key 和 URL
|
|
// 允许通过配置覆盖默认 Key 和 URL
|
|
|
- const apiKey = config?.apiKey || this.API_KEY;
|
|
|
|
|
- const baseURL = config?.serverURL || this.BASE_URL;
|
|
|
|
|
-
|
|
|
|
|
- this.axiosInstance = axios.create({
|
|
|
|
|
- baseURL,
|
|
|
|
|
- headers: {
|
|
|
|
|
- // TikHub 要求使用 Authorization: Bearer <token>
|
|
|
|
|
- 'Authorization': `Bearer ${apiKey}`,
|
|
|
|
|
- 'Content-Type': 'application/json'
|
|
|
|
|
- }
|
|
|
|
|
- });
|
|
|
|
|
|
|
+ this.apiKey = config?.apiKey || 'tKIbAsEM8X+GmE2vHqGW7D/ICwK1Q5V4viKFrWiPB6HholGdLFqZJmmyNw==';
|
|
|
|
|
+ this.baseURL = config?.serverURL || 'https://api.tikhub.io/api/v1';
|
|
|
|
|
+
|
|
|
|
|
+ this.headers = {
|
|
|
|
|
+ 'Authorization': `Bearer ${this.apiKey}`,
|
|
|
|
|
+ 'Content-Type': 'application/json'
|
|
|
|
|
+ };
|
|
|
|
|
+ }
|
|
|
|
|
|
|
|
- // 添加请求拦截器用于调试
|
|
|
|
|
- this.axiosInstance.interceptors.request.use(request => {
|
|
|
|
|
- console.log(`[TikHub] ${request.method?.toUpperCase()} ${request.baseURL}${request.url}`, request.params || request.data);
|
|
|
|
|
- return request;
|
|
|
|
|
- });
|
|
|
|
|
|
|
+ /**
|
|
|
|
|
+ * 构建完整 URL(包含查询参数)
|
|
|
|
|
+ */
|
|
|
|
|
+ private buildURL(path: string, params?: Record<string, any>): string {
|
|
|
|
|
+ const url = new URL(path, this.baseURL);
|
|
|
|
|
+
|
|
|
|
|
+ if (params) {
|
|
|
|
|
+ Object.entries(params).forEach(([key, value]) => {
|
|
|
|
|
+ if (value !== undefined && value !== null) {
|
|
|
|
|
+ url.searchParams.append(key, String(value));
|
|
|
|
|
+ }
|
|
|
|
|
+ });
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ return url.toString();
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
/**
|
|
@@ -37,16 +44,36 @@ export class TikHubClient {
|
|
|
* @param url 请求路径
|
|
* @param url 请求路径
|
|
|
* @param params 查询参数
|
|
* @param params 查询参数
|
|
|
*/
|
|
*/
|
|
|
- async get<T = any>(url: string, params: any = {}): Promise<T> {
|
|
|
|
|
|
|
+ async get<T = any>(url: string, params: Record<string, any> = {}): Promise<T> {
|
|
|
|
|
+ const fullURL = this.buildURL(url, params);
|
|
|
|
|
+
|
|
|
|
|
+ console.log(`[TikHub] GET ${fullURL}`);
|
|
|
|
|
+
|
|
|
try {
|
|
try {
|
|
|
- const response = await this.axiosInstance.get<T>(url, { params });
|
|
|
|
|
- return response.data;
|
|
|
|
|
- } catch (error: any) {
|
|
|
|
|
- console.error(`TikHub API Error [GET ${url}]:`, error.response?.data || error.message);
|
|
|
|
|
- // 打印完整的错误响应,帮助排查 400 原因
|
|
|
|
|
- if (error.response?.data) {
|
|
|
|
|
- console.error('Error Details:', JSON.stringify(error.response.data, null, 2));
|
|
|
|
|
|
|
+ const response = await fetch(fullURL, {
|
|
|
|
|
+ method: 'GET',
|
|
|
|
|
+ headers: this.headers
|
|
|
|
|
+ });
|
|
|
|
|
+
|
|
|
|
|
+ if (!response.ok) {
|
|
|
|
|
+ const errorText = await response.text();
|
|
|
|
|
+ let errorData;
|
|
|
|
|
+ try {
|
|
|
|
|
+ errorData = JSON.parse(errorText);
|
|
|
|
|
+ } catch {
|
|
|
|
|
+ errorData = { message: errorText };
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ console.error(`TikHub API Error [GET ${url}]:`, errorData);
|
|
|
|
|
+ console.error('Error Details:', JSON.stringify(errorData, null, 2));
|
|
|
|
|
+
|
|
|
|
|
+ throw new Error(`HTTP ${response.status}: ${JSON.stringify(errorData)}`);
|
|
|
}
|
|
}
|
|
|
|
|
+
|
|
|
|
|
+ const data = await response.json();
|
|
|
|
|
+ return data as T;
|
|
|
|
|
+ } catch (error: any) {
|
|
|
|
|
+ console.error(`TikHub API Error [GET ${url}]:`, error.message);
|
|
|
throw error;
|
|
throw error;
|
|
|
}
|
|
}
|
|
|
}
|
|
}
|
|
@@ -56,12 +83,35 @@ export class TikHubClient {
|
|
|
* @param url 请求路径
|
|
* @param url 请求路径
|
|
|
* @param data 请求体
|
|
* @param data 请求体
|
|
|
*/
|
|
*/
|
|
|
- async post<T = any>(url: string, data: any = {}): Promise<T> {
|
|
|
|
|
|
|
+ async post<T = any>(url: string, data: Record<string, any> = {}): Promise<T> {
|
|
|
|
|
+ const fullURL = this.buildURL(url);
|
|
|
|
|
+
|
|
|
|
|
+ console.log(`[TikHub] POST ${fullURL}`, data);
|
|
|
|
|
+
|
|
|
try {
|
|
try {
|
|
|
- const response = await this.axiosInstance.post<T>(url, data);
|
|
|
|
|
- return response.data;
|
|
|
|
|
|
|
+ const response = await fetch(fullURL, {
|
|
|
|
|
+ method: 'POST',
|
|
|
|
|
+ headers: this.headers,
|
|
|
|
|
+ body: JSON.stringify(data)
|
|
|
|
|
+ });
|
|
|
|
|
+
|
|
|
|
|
+ if (!response.ok) {
|
|
|
|
|
+ const errorText = await response.text();
|
|
|
|
|
+ let errorData;
|
|
|
|
|
+ try {
|
|
|
|
|
+ errorData = JSON.parse(errorText);
|
|
|
|
|
+ } catch {
|
|
|
|
|
+ errorData = { message: errorText };
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ console.error(`TikHub API Error [POST ${url}]:`, errorData);
|
|
|
|
|
+ throw new Error(`HTTP ${response.status}: ${JSON.stringify(errorData)}`);
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ const responseData = await response.json();
|
|
|
|
|
+ return responseData as T;
|
|
|
} catch (error: any) {
|
|
} catch (error: any) {
|
|
|
- console.error(`TikHub API Error [POST ${url}]:`, error.response?.data || error.message);
|
|
|
|
|
|
|
+ console.error(`TikHub API Error [POST ${url}]:`, error.message);
|
|
|
throw error;
|
|
throw error;
|
|
|
}
|
|
}
|
|
|
}
|
|
}
|