发现于 objectstack#5316 实施途中(PR 见下)。修法本身正确,这条是它的一个可测量副作用,单独立单由 PM 定级。
事实(实测)
objectstack#5316 把 packages/app-shell/src/views/metadata-admin/clientValidation.ts 的 view 编辑路从授权门(ViewItemSchema)改为 wire 门(ViewMetadataSchema)—— 这是对的,ViewMetadataSchema 正是 view 元数据类型注册、服务端 saveMetaItem 所判的那个 schema,客户端与服务端因此按构造同集。
但 ViewMetadataSchema 是 z.preprocess(strip, z.union([...4 个成员]))。Zod 对 union 失败只产出一条根级 invalid_union,逐成员的真实 issue 埋在它的嵌套 errors 里。validateMetadataDraft 的映射是逐字照搬:
path: (i.path ?? []).map(String).join('.'),
message: i.message,
于是同一份坏 body,两条路给出的诊断质量差距很大(实测,body 为一份 stored ViewItem,config.type 写成 not_a_real_layout):
| 门 |
path |
message |
ViewItemSchema(创建路,现状) |
config.type |
Invalid option: expected one of "grid"|"kanban"|"gallery"|… |
ViewItemWireSchema(仅作对照) |
config.type |
同上 |
ViewMetadataSchema(编辑路,#5316 之后) |
`` (空) |
Invalid input |
容器路同样塌陷:一份带未知键的 container,ViewSchema 会给出 spec 精心撰写的那条长消息(Unrecognized key(s) on this view container: … Wrap it: defineView({...})),经 ViewMetadataSchema 后只剩 Invalid input。
影响
SchemaForm 按 path 做逐字段内联高亮,Monaco 也按 path 定位。path 为空意味着:
- 编辑一份 stored view 时若 body 真的坏了,用户只看到一条无字段指向的「Invalid input」;
- spec 为这些拒绝专门写的引导性消息(#4001 那批)在编辑路上完全看不到。
这与 clientValidation.ts 自己的存在理由相抵 —— 文件头写的是「so we no longer have to wait for the next save round-trip to learn the draft is invalid」。判定(ok/not ok)仍然正确,丢的是可操作性。
触发条件:在 metadata-admin 里编辑一份 stored view 且 body 确实非法。合法 body 不受影响(#5316 之后正常通过)。
不是什么
- 不是要求回退 #5316。
ViewItemWireSchema 已被实测排除:它只覆盖 ViewItem 记录,且仍会以 config.filter.0: unrecognized_keys 误拒 console 过滤器构建器写入的行 id —— 那条 decoration 由 ViewMetadataSchema 的 z.preprocess 剥除,而 preprocess 跑在所有成员之前,能够到成员级 .strip() 够不到的嵌套块(spec 在 union 定义处自己写明了这一点)。
- 不是 try-both 兜底的入口。判定必须仍然只有一个门;这里要动的只是失败之后如何呈现,不是「换个 schema 再试一次能不能过」。
可能的方向(未实现,留给分诊)
把根级 invalid_union 的嵌套 errors 展开成可用 issue。难点在于选哪个成员的错误呈现 —— 四个成员都会报错,直接全展开会把「这不是 container」这类噪音摆到用户脸上。几个候选:
- 按 body 自身的判别式选成员(
viewKind 在则取 ViewItem wire 成员)—— 复用本文件已有且已文档化的 viewSchemaForDraft 判别逻辑,但会耦合 union 的成员顺序(spec 内部细节)。
- 选 issue 数最少 / path 最深的分支 —— 顺序无关,但是启发式,容器场景实测会选错(容器带未知键时,ViewItem 分支的
viewKind 错误 path 更深却是错误的消息)。
- 由 spec 侧提供一个「诊断用」入口(例如按判别式导出成员,或让 union 附带 discriminator),让消费方不必猜。契约优先,但跨仓。
倾向 3 或 1;不建议 2(启发式已实测会误选)。具体取舍请分诊裁决 —— 这是呈现层的取舍,不影响判定正确性。
仓库:objectui(packages/app-shell/src/views/metadata-admin/clientValidation.ts)。相关:objectstack#5316、objectstack#5074、objectui#3312。
发现于 objectstack#5316 实施途中(PR 见下)。修法本身正确,这条是它的一个可测量副作用,单独立单由 PM 定级。
事实(实测)
objectstack#5316 把
packages/app-shell/src/views/metadata-admin/clientValidation.ts的view编辑路从授权门(ViewItemSchema)改为 wire 门(ViewMetadataSchema)—— 这是对的,ViewMetadataSchema正是view元数据类型注册、服务端saveMetaItem所判的那个 schema,客户端与服务端因此按构造同集。但
ViewMetadataSchema是z.preprocess(strip, z.union([...4 个成员]))。Zod 对 union 失败只产出一条根级invalid_union,逐成员的真实 issue 埋在它的嵌套errors里。validateMetadataDraft的映射是逐字照搬:于是同一份坏 body,两条路给出的诊断质量差距很大(实测,body 为一份 stored ViewItem,
config.type写成not_a_real_layout):ViewItemSchema(创建路,现状)config.typeInvalid option: expected one of "grid"|"kanban"|"gallery"|…ViewItemWireSchema(仅作对照)config.typeViewMetadataSchema(编辑路,#5316 之后)Invalid input容器路同样塌陷:一份带未知键的 container,
ViewSchema会给出 spec 精心撰写的那条长消息(Unrecognized key(s) on this view container: … Wrap it: defineView({...})),经ViewMetadataSchema后只剩Invalid input。影响
SchemaForm按path做逐字段内联高亮,Monaco 也按 path 定位。path 为空意味着:这与
clientValidation.ts自己的存在理由相抵 —— 文件头写的是「so we no longer have to wait for the next save round-trip to learn the draft is invalid」。判定(ok/not ok)仍然正确,丢的是可操作性。触发条件:在 metadata-admin 里编辑一份 stored view 且 body 确实非法。合法 body 不受影响(#5316 之后正常通过)。
不是什么
ViewItemWireSchema已被实测排除:它只覆盖 ViewItem 记录,且仍会以config.filter.0: unrecognized_keys误拒 console 过滤器构建器写入的行id—— 那条 decoration 由ViewMetadataSchema的z.preprocess剥除,而 preprocess 跑在所有成员之前,能够到成员级.strip()够不到的嵌套块(spec 在 union 定义处自己写明了这一点)。可能的方向(未实现,留给分诊)
把根级
invalid_union的嵌套errors展开成可用 issue。难点在于选哪个成员的错误呈现 —— 四个成员都会报错,直接全展开会把「这不是 container」这类噪音摆到用户脸上。几个候选:viewKind在则取 ViewItem wire 成员)—— 复用本文件已有且已文档化的viewSchemaForDraft判别逻辑,但会耦合 union 的成员顺序(spec 内部细节)。viewKind错误 path 更深却是错误的消息)。倾向 3 或 1;不建议 2(启发式已实测会误选)。具体取舍请分诊裁决 —— 这是呈现层的取舍,不影响判定正确性。
仓库:objectui(
packages/app-shell/src/views/metadata-admin/clientValidation.ts)。相关:objectstack#5316、objectstack#5074、objectui#3312。