Skip to content

ObjectDataPage「Save as view」把 URL filter 三元组原样写进 ViewItem,产出过不了 ViewItemSchema #3419

Description

@yinlianghui

发现于 #3375(给 viewEnvelope 补 ViewItem spec 一致性 pin 时),不在该 PR 的 fence 内(属运行时行为改动),故单独记录。

现象

packages/app-shell/src/views/ObjectDataPage.tsxhandleSaveAsView(约 250-254 行)把当前 URL 上的下钻条件原样塞进要持久化的 view spec:

const spec: Record< string, any > = {
  ...config,
  columns: ...,
  ...(urlFilters.length ? { filter: urlFilters } : {}),
};
const env = viewEnvelope(objectName ?? '', spec, { ... });
await createRuntimeMetadata('view', env.name, env, { metadataClient });

urlFiltersFilterTriple[](drillUrlFilters.ts:23:[string, string, unknown] —— 三元组数组),@objectstack/spec 的 ViewItem list config 里 filter 要求的是 ViewFilterRuleSchema 对象数组({ field, operator, value },且 operator 取规范枚举 equals 等,不是 =)。

复现(spec@17.0.0-rc.2,即当前 lockfile 解析版本)

viewEnvelope 在该调用点的实际产出喂给记录门:

config.filter = [['stage','=','open']]
ViewItemSchema.safeParse(env) -> false
[{"expected":"object","code":"invalid_type","path":["config","filter",0],
  "message":"Invalid input: expected object, received array"}]

对照:builder 那条路径是对的 —— viewFilterFold.foldFilterGroupToSpecRules(viewFilterFold.ts:122)产出 { field, operator, value },并且用 normalizeFilterOperator 把 operator 规范化过,产出可以过门。也就是说同一个 filter 键在本仓存在两种写法,只有 fold 那条符合 spec

影响

带下钻条件时点「Save as view」,写出去的是一条 off-spec 的 ViewItem。ADR-0017 记录门若在发布/校验侧收紧,这条 view 会被拒;在此之前它以第二种事实方言的形式沉淀下来。

建议方向(交由 triage 定夺)

契约优先:在 producer 侧把三元组折成 spec 的 rule 对象再进 viewEnvelope(复用 normalizeFilterOperator,与 viewFilterFold 同一出口),而不是在消费侧容忍三元组。

备注

#3375 的 pin 只覆盖 viewEnvelope 自身的产出契约,对这条走的是「按 spec 形状的 filter rules」用例;三元组这条留给本 issue,以免把运行时改动混进纯 pin PR。

Metadata

Metadata

Assignees

Type

No type

Projects

No projects

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions