|
@@ -0,0 +1,59 @@
|
|
|
|
|
+import { z } from '@hono/zod-openapi';
|
|
|
|
|
+
|
|
|
|
|
+export async function parseWithAwait<T>(schema: z.ZodSchema<T>, data: unknown): Promise<T> {
|
|
|
|
|
+ // 先尝试同步解析,捕获 Promise 错误
|
|
|
|
|
+ const syncResult = schema.safeParse(data);
|
|
|
|
|
+
|
|
|
|
|
+ if (!syncResult.success) {
|
|
|
|
|
+ // 提取 Promise 错误的路径信息
|
|
|
|
|
+ const promiseErrors = syncResult.error.issues.filter(issue =>
|
|
|
|
|
+ issue.code === 'invalid_type' &&
|
|
|
|
|
+ issue.message.includes('received Promise')
|
|
|
|
|
+ );
|
|
|
|
|
+
|
|
|
|
|
+ if (promiseErrors.length > 0) {
|
|
|
|
|
+ // 根据路径直接 await Promise
|
|
|
|
|
+ const processedData = await resolvePromisesByPath(data, promiseErrors);
|
|
|
|
|
+
|
|
|
|
|
+ // 重新解析处理后的数据
|
|
|
|
|
+ return schema.parse(processedData) as T;
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ throw syncResult.error;
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ return syncResult.data as T;
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ async function resolvePromisesByPath(data: any, promiseErrors: any[]): Promise<any> {
|
|
|
|
|
+ const clonedData = JSON.parse(JSON.stringify(data, (key, value) => {
|
|
|
|
|
+ // 保留 Promise 对象,不进行序列化
|
|
|
|
|
+ return typeof value?.then === 'function' ? value : value;
|
|
|
|
|
+ }));
|
|
|
|
|
+
|
|
|
|
|
+ // 根据错误路径逐个处理 Promise
|
|
|
|
|
+ for (const error of promiseErrors) {
|
|
|
|
|
+ const path = error.path;
|
|
|
|
|
+ const promiseValue = getValueByPath(data, path);
|
|
|
|
|
+
|
|
|
|
|
+ if (promiseValue && typeof promiseValue.then === 'function') {
|
|
|
|
|
+ const resolvedValue = await promiseValue;
|
|
|
|
|
+ setValueByPath(clonedData, path, resolvedValue);
|
|
|
|
|
+ }
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ return clonedData;
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ function getValueByPath(obj: any, path: (string | number)[]): any {
|
|
|
|
|
+ return path.reduce((current, key) => current?.[key], obj);
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ function setValueByPath(obj: any, path: (string | number)[], value: any): void {
|
|
|
|
|
+ const lastKey = path[path.length - 1];
|
|
|
|
|
+ const parentPath = path.slice(0, -1);
|
|
|
|
|
+ const parent = getValueByPath(obj, parentPath);
|
|
|
|
|
+ if (parent) {
|
|
|
|
|
+ parent[lastKey] = value;
|
|
|
|
|
+ }
|
|
|
|
|
+ }
|