文档先行:AGC 认证错误的 TS 形状改为每个变体一个具名载荷类型
- ADR §1 增加"每个变体一个具名载荷结构体 + ts-rs 生成 `{ type } & X`"的决策与代价
- ADR §3 说明 switch 分支里错误已窄化成具名类型
- 技术方案同步命令错误形状描述
- decision-log / pitfalls 记录形状约定:不手写这层类型、不再包派生分类与提示文案函数
This commit is contained in:
@@ -33,6 +33,12 @@ DirectProject 已经解决过同一类问题([`【ADR】DirectProject命令接
|
||||
- Rust 侧定义具体变体枚举(auth 首个落地:`ClientAuthError`),`#[derive(Serialize, TS)]` +
|
||||
`#[serde(tag = "type", rename_all = "camelCase")]`,用 ts-rs 导出到
|
||||
`apps/ai-game-creator-shell/src/services/generated/`;生成物不手改。
|
||||
- **每个变体一个具名载荷结构体**,枚举用 newtype 变体持有它(`PhoneNumberInvalid(PhoneNumberInvalid)`)。
|
||||
ts-rs 因此生成 `{ type: 'phoneNumberInvalid' } & PhoneNumberInvalid`,以及每个变体一个
|
||||
`generated/<变体名>.ts`:前端 `switch (error.type)` 的每个分支都落到一个有名字的类型,等价于 Java 的
|
||||
`catch (PhoneNumberInvalid e)`,不需要 `as` 断言,载荷类型自己带 JSDoc。载荷必须能序列化成 map
|
||||
(serde 的 internally tagged 表示只接受 struct / map),所以没有无字段变体;代价是 Rust 构造点统一写成
|
||||
`ClientAuthError::X(X { message })`。这个形状在本仓已有先例(`DirectCodexUserContentPart`)。
|
||||
- `#[tauri::command]` 的 `Err` 直接携带该枚举(Tauri 2 的 `InvokeError(pub serde_json::Value)` 支持结构化错误)。
|
||||
这是 DirectProject 已有的做法(`enqueue_direct_codex_turn -> Result<(), DirectTurnEnqueueFailure>`),不是新约定。
|
||||
- 变体按**可判定的事实**命名。服务端 400 只提供 `status + message`(`AppError.code` 仍是通用
|
||||
@@ -57,7 +63,8 @@ DirectProject 已经解决过同一类问题([`【ADR】DirectProject命令接
|
||||
|
||||
- `isClientAuthError` 只做形状读取(`type` 是稳定判别键),**不做分类、不产出派生值**。
|
||||
- 调用方自己 `switch (error.type)`,逐个列出具体变体:业务输入 / 会话变体给提示,`default`(系统变体
|
||||
与 Rust 新增而界面没接的变体)带上文交池。判据是具体变体名,不是聚合出来的类别,也不是文案匹配。
|
||||
与 Rust 新增而界面没接的变体)带上文交池。判据是具体变体名,不是聚合出来的类别,也不是文案匹配;
|
||||
每个 `case` 里 `error` 已窄化成 §1 的具名载荷类型(如 `PhoneNumberInvalid`)。
|
||||
- 认不出、系统类、非结构化拒绝 → 调用方包成 `ClientActionError(message, context, cause)` 交给
|
||||
`captureClientError`:`instanceof` 解包 `context` 与 `cause`,指纹/展示字段与今天一致。
|
||||
**不把 rejection 留在没人接手的 Promise 上**:`onSubmit` / `onClick` 这类 `void` 掉的 handler 抛错
|
||||
|
||||
Reference in New Issue
Block a user