Files
image-processing/electron/main/server-api.ts
T

103 lines
2.9 KiB
TypeScript
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
import { app, net } from 'electron'
import type {
LicenseSession,
VersionInfo,
} from '../../src/shared/types'
import { buildDesktopRequestHeaders } from './server-api-headers'
interface ApiResult<T> {
code: string
msg: string
data: T
}
export interface DevicePayload {
deviceId: string
deviceName: string
osName: string
osVersion: string
appVersion: string
}
export class ServerApiError extends Error {
constructor(
public readonly code: string,
message: string,
) {
super(message)
this.name = 'ServerApiError'
}
}
const DEFAULT_API_BASE_URL = 'https://apimall.v2.jxxyk.com/api'
export class DesktopServerApi {
private readonly baseUrl: string
constructor(baseUrl = process.env.IMAGE_TOOL_API_BASE_URL || DEFAULT_API_BASE_URL) {
this.baseUrl = this.validateBaseUrl(baseUrl)
}
activate(activationCode: string, device: DevicePayload): Promise<LicenseSession> {
return this.post<LicenseSession>('/desktop/activate', {
activationCode,
...device,
})
}
login(token: string, device: DevicePayload): Promise<LicenseSession> {
return this.post<LicenseSession>('/desktop/login', {
token,
...device,
})
}
checkVersion(currentVersion: string): Promise<VersionInfo> {
return this.post<VersionInfo>('/desktop/version/check', {
currentVersion,
platform: 'windows',
})
}
private async post<T>(pathname: string, body: unknown): Promise<T> {
const controller = new AbortController()
const timeout = setTimeout(() => controller.abort(), 15_000)
try {
const response = await net.fetch(`${this.baseUrl}${pathname}`, {
method: 'POST',
headers: buildDesktopRequestHeaders(app.getVersion()),
body: JSON.stringify(body),
signal: controller.signal,
})
if (!response.ok) {
throw new ServerApiError(String(response.status), `授权服务暂时不可用(${response.status})`)
}
const result = (await response.json()) as ApiResult<T>
if (result.code !== '0') {
throw new ServerApiError(result.code, result.msg || '授权校验失败')
}
return result.data
} catch (error) {
if (error instanceof ServerApiError) {
throw error
}
if (error instanceof Error && error.name === 'AbortError') {
throw new ServerApiError('NETWORK_TIMEOUT', '连接授权服务超时,请检查网络后重试')
}
throw new ServerApiError('NETWORK_ERROR', '无法连接授权服务,请检查网络后重试')
} finally {
clearTimeout(timeout)
}
}
private validateBaseUrl(value: string): string {
const url = new URL(value.trim())
const localDevelopment = url.protocol === 'http:'
&& ['127.0.0.1', 'localhost'].includes(url.hostname)
if (url.protocol !== 'https:' && !(localDevelopment && !app.isPackaged)) {
throw new Error('生产授权服务必须使用 HTTPS')
}
return url.toString().replace(/\/$/, '')
}
}