108 lines
3.8 KiB
TypeScript
108 lines
3.8 KiB
TypeScript
import { apiClient } from '../api/api-client';
|
|
import {
|
|
AppVersion,
|
|
AppVersionFilter,
|
|
UpdateAppVersionInput,
|
|
UploadAppVersionInput,
|
|
ParsedPackageInfo,
|
|
} from '@/domain/entities/app-version';
|
|
|
|
/** Normalize version-service response: platform comes back as ANDROID/IOS, fileSize as bigint string */
|
|
function normalize(raw: Record<string, unknown>): AppVersion {
|
|
return {
|
|
...(raw as AppVersion),
|
|
platform: (raw.platform as string).toLowerCase() as 'android' | 'ios',
|
|
fileSize: raw.fileSize != null ? Number(raw.fileSize) : undefined,
|
|
};
|
|
}
|
|
|
|
export async function listVersions(filter?: AppVersionFilter): Promise<AppVersion[]> {
|
|
const params = new URLSearchParams();
|
|
if (filter?.platform) params.append('platform', filter.platform.toUpperCase());
|
|
if (filter?.includeDisabled) params.append('includeDisabled', 'true');
|
|
const qs = params.toString();
|
|
const result = await apiClient<unknown[]>(`/api/v1/versions${qs ? '?' + qs : ''}`);
|
|
return result.map((v) => normalize(v as Record<string, unknown>));
|
|
}
|
|
|
|
export async function getVersionById(id: string): Promise<AppVersion> {
|
|
const result = await apiClient<unknown>(`/api/v1/versions/${id}`);
|
|
return normalize(result as Record<string, unknown>);
|
|
}
|
|
|
|
export async function updateVersion(id: string, input: UpdateAppVersionInput): Promise<AppVersion> {
|
|
const result = await apiClient<unknown>(`/api/v1/versions/${id}`, { method: 'PUT', body: input });
|
|
return normalize(result as Record<string, unknown>);
|
|
}
|
|
|
|
export async function deleteVersion(id: string): Promise<void> {
|
|
await apiClient<unknown>(`/api/v1/versions/${id}`, { method: 'DELETE' });
|
|
}
|
|
|
|
export async function toggleVersion(id: string, isEnabled: boolean): Promise<void> {
|
|
await apiClient<unknown>(`/api/v1/versions/${id}/toggle`, {
|
|
method: 'PATCH',
|
|
body: { isEnabled },
|
|
});
|
|
}
|
|
|
|
function getClientAuthHeaders(): Record<string, string> {
|
|
const headers: Record<string, string> = {};
|
|
if (typeof window === 'undefined') return headers;
|
|
const token = localStorage.getItem('access_token');
|
|
if (token) headers['Authorization'] = `Bearer ${token}`;
|
|
const tenantData = localStorage.getItem('current_tenant');
|
|
if (tenantData) {
|
|
try {
|
|
const tenant = JSON.parse(tenantData) as { id: string };
|
|
headers['X-Tenant-Id'] = tenant.id;
|
|
} catch {
|
|
// ignore parse errors
|
|
}
|
|
}
|
|
return headers;
|
|
}
|
|
|
|
export async function uploadVersion(input: UploadAppVersionInput): Promise<AppVersion> {
|
|
const formData = new FormData();
|
|
formData.append('file', input.file);
|
|
formData.append('platform', input.platform.toUpperCase());
|
|
formData.append('versionName', input.versionName);
|
|
formData.append('buildNumber', input.buildNumber);
|
|
formData.append('isForceUpdate', String(input.isForceUpdate ?? false));
|
|
if (input.changelog) formData.append('changelog', input.changelog);
|
|
if (input.minOsVersion) formData.append('minOsVersion', input.minOsVersion);
|
|
|
|
const response = await fetch('/api/app-versions/upload', {
|
|
method: 'POST',
|
|
headers: getClientAuthHeaders(),
|
|
body: formData,
|
|
});
|
|
|
|
if (!response.ok) {
|
|
const err = await response.json().catch(() => null) as { message?: string } | null;
|
|
throw new Error(err?.message || `上传失败: ${response.status}`);
|
|
}
|
|
|
|
const result = await response.json() as Record<string, unknown>;
|
|
return normalize(result);
|
|
}
|
|
|
|
export async function parsePackage(file: File, platform: 'android' | 'ios'): Promise<ParsedPackageInfo> {
|
|
const formData = new FormData();
|
|
formData.append('file', file);
|
|
formData.append('platform', platform.toUpperCase());
|
|
|
|
const response = await fetch('/api/app-versions/parse', {
|
|
method: 'POST',
|
|
headers: getClientAuthHeaders(),
|
|
body: formData,
|
|
});
|
|
|
|
if (!response.ok) {
|
|
throw new Error(`解析失败: ${response.status}`);
|
|
}
|
|
|
|
return response.json() as Promise<ParsedPackageInfo>;
|
|
}
|