118 lines
3.1 KiB
JavaScript
118 lines
3.1 KiB
JavaScript
|
|
/**
|
|||
|
|
* 通用验证工具函数
|
|||
|
|
* Common validation utility functions
|
|||
|
|
*/
|
|||
|
|
import * as v from 'valibot';
|
|||
|
|
/**
|
|||
|
|
* 将 Valibot 验证错误转换为自定义格式
|
|||
|
|
* Convert Valibot validation errors to custom format
|
|||
|
|
*/
|
|||
|
|
export function formatValidationErrors(issues) {
|
|||
|
|
return issues.map(issue => ({
|
|||
|
|
field: issue.path?.map(p => p.key).join('.') || 'unknown',
|
|||
|
|
message: issue.message,
|
|||
|
|
code: issue.type || 'VALIDATION_ERROR',
|
|||
|
|
}));
|
|||
|
|
}
|
|||
|
|
/**
|
|||
|
|
* 安全解析数据
|
|||
|
|
* Safely parse data with validation
|
|||
|
|
*/
|
|||
|
|
export function safeParseData(schema, data) {
|
|||
|
|
try {
|
|||
|
|
const result = v.safeParse(schema, data);
|
|||
|
|
if (result.success) {
|
|||
|
|
return {
|
|||
|
|
success: true,
|
|||
|
|
data: result.output,
|
|||
|
|
};
|
|||
|
|
}
|
|||
|
|
else {
|
|||
|
|
return {
|
|||
|
|
success: false,
|
|||
|
|
errors: formatValidationErrors(result.issues),
|
|||
|
|
};
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
catch (error) {
|
|||
|
|
return {
|
|||
|
|
success: false,
|
|||
|
|
errors: [
|
|||
|
|
{
|
|||
|
|
field: 'unknown',
|
|||
|
|
message: error instanceof Error ? error.message : '验证过程中发生未知错误',
|
|||
|
|
code: 'UNKNOWN_ERROR',
|
|||
|
|
},
|
|||
|
|
],
|
|||
|
|
};
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
/**
|
|||
|
|
* 解析并验证数据,失败时抛出错误
|
|||
|
|
* Parse and validate data, throw error on failure
|
|||
|
|
*/
|
|||
|
|
export function parseData(schema, data) {
|
|||
|
|
const result = safeParseData(schema, data);
|
|||
|
|
if (!result.success) {
|
|||
|
|
const error = new Error('数据验证失败');
|
|||
|
|
error.statusCode = 400;
|
|||
|
|
error.validationErrors = result.errors;
|
|||
|
|
throw error;
|
|||
|
|
}
|
|||
|
|
return result.data;
|
|||
|
|
}
|
|||
|
|
/**
|
|||
|
|
* 创建验证中间件函数(用于 API)
|
|||
|
|
* Create validation middleware function (for API)
|
|||
|
|
*/
|
|||
|
|
export function createValidationMiddleware(schema) {
|
|||
|
|
return (data) => {
|
|||
|
|
return parseData(schema, data);
|
|||
|
|
};
|
|||
|
|
}
|
|||
|
|
/**
|
|||
|
|
* 验证查询参数
|
|||
|
|
* Validate query parameters
|
|||
|
|
*/
|
|||
|
|
export function validateQuery(schema, query) {
|
|||
|
|
// 转换查询参数中的数字字符串
|
|||
|
|
const processedQuery = Object.entries(query).reduce((acc, [key, value]) => {
|
|||
|
|
if (value === undefined || value === null || value === '') {
|
|||
|
|
return acc;
|
|||
|
|
}
|
|||
|
|
// 尝试转换数字
|
|||
|
|
if (typeof value === 'string' && !isNaN(Number(value))) {
|
|||
|
|
acc[key] = Number(value);
|
|||
|
|
}
|
|||
|
|
else {
|
|||
|
|
acc[key] = value;
|
|||
|
|
}
|
|||
|
|
return acc;
|
|||
|
|
}, {});
|
|||
|
|
return parseData(schema, processedQuery);
|
|||
|
|
}
|
|||
|
|
/**
|
|||
|
|
* 验证请求体数据
|
|||
|
|
* Validate request body data
|
|||
|
|
*/
|
|||
|
|
export function validateBody(schema, body) {
|
|||
|
|
return parseData(schema, body);
|
|||
|
|
}
|
|||
|
|
/**
|
|||
|
|
* 验证路径参数
|
|||
|
|
* Validate path parameters
|
|||
|
|
*/
|
|||
|
|
export function validateParams(schema, params) {
|
|||
|
|
// 转换路径参数中的数字字符串
|
|||
|
|
const processedParams = Object.entries(params).reduce((acc, [key, value]) => {
|
|||
|
|
if (typeof value === 'string' && !isNaN(Number(value))) {
|
|||
|
|
acc[key] = Number(value);
|
|||
|
|
}
|
|||
|
|
else {
|
|||
|
|
acc[key] = value;
|
|||
|
|
}
|
|||
|
|
return acc;
|
|||
|
|
}, {});
|
|||
|
|
return parseData(schema, processedParams);
|
|||
|
|
}
|
|||
|
|
//# sourceMappingURL=validation.js.map
|