refactor: centralize API client and config caching

This commit is contained in:
hkfires
2025-11-21 09:42:16 +08:00
parent 93eb7f4717
commit a8b8bdc11c
6 changed files with 208 additions and 119 deletions

62
src/core/api-client.js Normal file
View File

@@ -0,0 +1,62 @@
// API 客户端:负责规范化基础地址、构造完整 URL、发送请求并回传版本信息
export class ApiClient {
constructor({ apiBase = '', managementKey = '', onVersionUpdate = null } = {}) {
this.apiBase = '';
this.apiUrl = '';
this.managementKey = managementKey || '';
this.onVersionUpdate = onVersionUpdate;
this.setApiBase(apiBase);
}
normalizeBase(input) {
let base = (input || '').trim();
if (!base) return '';
base = base.replace(/\/?v0\/management\/?$/i, '');
base = base.replace(/\/+$/i, '');
if (!/^https?:\/\//i.test(base)) {
base = 'http://' + base;
}
return base;
}
computeApiUrl(base) {
const normalized = this.normalizeBase(base);
if (!normalized) return '';
return normalized.replace(/\/$/, '') + '/v0/management';
}
setApiBase(newBase) {
this.apiBase = this.normalizeBase(newBase);
this.apiUrl = this.computeApiUrl(this.apiBase);
return this.apiUrl;
}
setManagementKey(key) {
this.managementKey = key || '';
}
async request(endpoint, options = {}) {
const url = `${this.apiUrl}${endpoint}`;
const headers = {
'Authorization': `Bearer ${this.managementKey}`,
'Content-Type': 'application/json',
...options.headers
};
const response = await fetch(url, {
...options,
headers
});
if (typeof this.onVersionUpdate === 'function') {
this.onVersionUpdate(response.headers);
}
if (!response.ok) {
const errorData = await response.json().catch(() => ({}));
throw new Error(errorData.error || `HTTP ${response.status}`);
}
return await response.json();
}
}