0.3.5 共享功能修复

This commit is contained in:
liaibo
2026-01-24 12:32:51 +08:00
parent 25923f308c
commit 3c3f407f4b
44 changed files with 3754 additions and 420 deletions
@@ -0,0 +1,28 @@
import { describe, expect, it } from "vitest";
import { getUserFacingErrorMessage } from "./errors";
describe("getUserFacingErrorMessage", () => {
it("在 message 很短时直接返回", () => {
expect(getUserFacingErrorMessage(new Error("未登录"), "fallback")).toBe("未登录");
});
it("能从 Convex 的长错误中提取 Uncaught Error 之后的消息", () => {
const err = new Error(
"[CONVEX M(users:setMyUsername)] [Request ID: xxx] Server Error Uncaught Error: 未登录 at handler (./convex/users.ts:41:10) Called by client",
);
expect(getUserFacingErrorMessage(err, "fallback")).toBe("未登录");
});
it("能从包含 Error: 的错误中提取关键信息", () => {
const err = new Error("Server Error Error: 用户名已被占用 at handler (./convex/users.ts:48:7)");
expect(getUserFacingErrorMessage(err, "fallback")).toBe("用户名已被占用");
});
it("字符串错误也能直接展示", () => {
expect(getUserFacingErrorMessage(" 保存失败 ", "fallback")).toBe("保存失败");
});
it("无法解析时返回 fallback", () => {
expect(getUserFacingErrorMessage({ foo: "bar" }, "fallback")).toBe("fallback");
});
});
+23
View File
@@ -0,0 +1,23 @@
/**
* 将各种错误对象(尤其是 Convex Client 抛出的长错误)转换为更适合展示给用户的短消息。
*/
export function getUserFacingErrorMessage(err: unknown, fallback: string): string {
if (!err) return fallback;
if (typeof err === "string") return err.trim() || fallback;
const record = typeof err === "object" && err !== null ? (err as Record<string, unknown>) : null;
const raw = typeof record?.message === "string" ? String(record.message) : "";
const oneLine = raw.split("\n")[0]?.trim() ?? "";
// Convex 有时会把服务端堆栈拼进 message 里,形如:
// "... Server Error Uncaught Error: 未登录 at handler (...)",这里尽量只取“未登录”。
const uncaught = raw.match(/Uncaught Error:\s*([^\n]+?)(?:\s+at\s|$)/i);
if (uncaught?.[1]) return uncaught[1].trim();
const plainError = raw.match(/Error:\s*([^\n]+?)(?:\s+at\s|$)/i);
if (plainError?.[1]) return plainError[1].trim();
if (oneLine) return oneLine;
return fallback;
}