59 行
1.4 KiB
TypeScript
59 行
1.4 KiB
TypeScript
|
|
import type { AxiosError, AxiosResponse } from 'axios'
|
||
|
|
import type { z } from 'zod'
|
||
|
|
|
||
|
|
type SafeIssue = {
|
||
|
|
code: string
|
||
|
|
message: string
|
||
|
|
path: string
|
||
|
|
}
|
||
|
|
|
||
|
|
export type SafeApiDiagnostic = {
|
||
|
|
code?: string
|
||
|
|
httpStatus?: number
|
||
|
|
issues?: SafeIssue[]
|
||
|
|
method?: string
|
||
|
|
path?: string
|
||
|
|
type: 'AxiosError' | 'Response' | 'ValidationError'
|
||
|
|
}
|
||
|
|
|
||
|
|
/**
|
||
|
|
* 网络诊断只能描述请求形态,不得复制请求/响应 body、headers 或完整 URL。
|
||
|
|
* 这些字段可能包含手机号、userId、sessionId、签名和其它业务数据。
|
||
|
|
*/
|
||
|
|
function requestShape(response: AxiosResponse<unknown>) {
|
||
|
|
return {
|
||
|
|
httpStatus: response.status,
|
||
|
|
method: response.config.method?.toUpperCase(),
|
||
|
|
path: response.config.url,
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
export function createResponseDiagnostic(response: AxiosResponse<unknown>): SafeApiDiagnostic {
|
||
|
|
return { type: 'Response', ...requestShape(response) }
|
||
|
|
}
|
||
|
|
|
||
|
|
export function createValidationDiagnostic(
|
||
|
|
response: AxiosResponse<unknown>,
|
||
|
|
issues: z.ZodIssue[],
|
||
|
|
): SafeApiDiagnostic {
|
||
|
|
return {
|
||
|
|
type: 'ValidationError',
|
||
|
|
...requestShape(response),
|
||
|
|
issues: issues.map(issue => ({
|
||
|
|
code: issue.code,
|
||
|
|
message: issue.message,
|
||
|
|
path: issue.path.join('.'),
|
||
|
|
})),
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
export function createAxiosDiagnostic(error: AxiosError): SafeApiDiagnostic {
|
||
|
|
return {
|
||
|
|
type: 'AxiosError',
|
||
|
|
code: error.code,
|
||
|
|
httpStatus: error.response?.status,
|
||
|
|
method: error.config?.method?.toUpperCase(),
|
||
|
|
path: error.config?.url,
|
||
|
|
}
|
||
|
|
}
|