feat(api, web): интеграция Macloud и VDSina через унифицированный UserAPI
Docker / build (push) Has been cancelled

Один модуль userapi для идентичного API обоих хостеров: синк VPS, баланса, тарифов и пополнений.

Co-authored-by: Cursor <[email protected]>
This commit is contained in:
Denozordec
2026-06-29 02:02:03 +07:00
co-authored by Cursor
parent 9be50aa03b
commit f2c4c7a412
18 changed files with 1469 additions and 32 deletions
+15 -2
View File
@@ -1,12 +1,25 @@
import { z } from 'zod'
export const API_TYPES = ['billmanager', '4vps', 'none'] as const
export const API_TYPES = ['billmanager', '4vps', 'macloud', 'vdsina', 'none'] as const
export type ApiType = (typeof API_TYPES)[number]
export const apiTypeSchema = z.enum(API_TYPES).optional().default('none')
export const SYNC_API_TYPES = ['billmanager', '4vps'] as const
export const SYNC_API_TYPES = ['billmanager', '4vps', 'macloud', 'vdsina'] as const
export type SyncApiType = (typeof SYNC_API_TYPES)[number]
export const USER_API_TYPES = ['macloud', 'vdsina'] as const
export type UserApiType = (typeof USER_API_TYPES)[number]
export const USER_API_DEFAULT_BASE_URL: Record<UserApiType, string> = {
macloud: 'https://userapi.macloud.ru/v1',
vdsina: 'https://userapi.vdsina.com/v1',
}
export function isUserApiType(apiType?: string | null): apiType is UserApiType {
const key = String(apiType || '').toLowerCase()
return (USER_API_TYPES as readonly string[]).includes(key)
}
export function isSyncApiType(apiType?: string | null): apiType is SyncApiType {
const key = String(apiType || '').toLowerCase()
return (SYNC_API_TYPES as readonly string[]).includes(key)
@@ -34,6 +34,11 @@ export function parseFourVpsCredentials(credentials: string | null | undefined):
}
}
/** Bearer token для Macloud / VDSina UserAPI. */
export function parseUserApiToken(credentials: string | null | undefined): string {
return String(credentials ?? '').trim()
}
/** Собрать 4VPS-креды: panelId + API key. */
export function buildFourVpsCredentials(panelId: string, apiKey: string): string {
const pid = panelId.trim()