Skip to content

toSortItems — a published export — still tolerantly reads the retired direction sort spelling (s.order || s.direction), dormant because nothing in-tree calls it #6011

Description

@yinlianghui

Found while reworking #5293 (the views-prop sort spelling rename). Filed unassigned, no labels — triage grades it. Deliberately NOT fixed in #5293's PR (#6008): removing a tolerant read from a published export is its own Clause-② public-export break and needs its own adjudication.

Verified on claude/issue-5293-viewsort-order-spelling @ 604c20366 (branch base 8d3a5294a).

The dual-read

packages/plugin-view/src/config/view-config-utils.ts:324-330:

/** Convert draft sort → SortItem[] for SortBuilder */exportfunctiontoSortItems(draftSort: any): SortItem[]{return(Array.isArray(draftSort) ? draftSort : []).map((s: any)=>({id: s.id||crypto.randomUUID(),field: s.field||'',order: (s.order||s.direction||'asc')as'asc'|'desc',}));}

s.order || s.direction || 'asc' accepts two spellings for one key and silently prefers the canonical one. That is precisely the shape #4869 ruled against — verbatim, unmodified:

defaultSort 实际存在 sink 不认的拼法,正确的动作是先裁定该拼法算不算已声明的 authoring surface(要么进 sink 的契约,要么在 producer 端拒绝),而不是在 ObjectView 里加一层容忍。

It is published: re-exported from the package root at packages/plugin-view/src/index.tsx:38 and documented in packages/plugin-view/README.md:91 (toSortItems, // sort config -> SortItem[]).

Why it survived

It has no in-repo production caller at all. git grep -n toSortItems -- packages apps examples returns exactly:

  • packages/plugin-view/src/config/view-config-utils.ts:324 — the definition
  • packages/plugin-view/src/index.tsx:38 — the export barrel
  • packages/plugin-view/README.md:91 — the doc line
  • apps/console/src/__tests__/insecure-origin-crypto.test.ts:20 / :226 / :244 — a test, and the only importer of the published symbol
  • packages/plugin-view/src/SortUI.tsx:58 / :81 / :86⚠️ a different, file-localconst toSortItems that shadows nothing and imports nothing; it maps SortEntry[], whose direction key is type-correct on SortUISchema. It is not a caller of the published export, and a naive grep will read it as one.

The surface it serves is the studio inspector-draft feeding SortBuilder, reached only by out-of-tree callers today. It was never on the resolved activeView.sort path that #5293 fixed, which is why #5293 correctly left it alone.

Why it still matters

#5293's changeset promises that the views[].sort break is "loud and searchable". A host migrating off direction greps the old key, lands on a published export that still quietly accepts it, and reasonably concludes the retirement is partial. One spelling repo-wide is the convergence direction #4869 set; this is the last dormant tolerance layer on the sort family's public surface.

Related stale-spelling fixture — recorded, not batched into this

packages/plugin-view/src/__tests__/ObjectView.filterSources.test.tsx:161-162:

const seen = renderDelegated({ table: { defaultSort: [{ field: 'name', direction: 'asc' }] } as any });
expect(seen[0]?.sort).toEqual([{ field: 'name', direction: 'asc' }]);

table.defaultSort is an ObjectGridSchema surface and it declares order, not direction (packages/types/src/objectql.ts:673-676; the zod mirror at packages/types/src/zod/objectql.zod.ts:130 agrees). The fixture writes the retired spelling behind an as any and stays green only because that test asserts verbatim pass-through — it never reads the key, so any word would pass. This is not a defect in ObjectView; it is a fixture pinned to a spelling its own surface does not declare, and it should be re-spelled (or replaced, if re-spelling would preserve the shape of a bug) by whoever takes this card.

What the fix costs — options for adjudication

Deleting || s.direction is one line but a published-export behaviour break: an out-of-tree caller passing { field, direction } goes from a working SortItem to a silent 'asc'.

  1. Remove the fallback. One spelling repo-wide, declared equals enforced. objectui ships its own breaks as minor per AGENTS.md §版本号策略, with a changeset naming the retired key — the same treatment ObjectViewProps.views[].sort declares direction, but every sort consumer reads order — a host-supplied desc view silently sorts ascending #5293 got. Matches [finding] ObjectView 是最后一处不走共享 sort sink 的读点 —— $orderby: sort 原样透传,归一化外包给了某一个 adapter #4869's direction.
  2. Keep the fallback but make it loud (reject, or warn, on direction). Converts a silent accept into a signal without dropping the input, at the cost of keeping the word alive in the contract.
  3. Leave it. Cheapest; the sort family keeps a tolerance layer and ObjectViewProps.views[].sort declares direction, but every sort consumer reads order — a host-supplied desc view silently sorts ascending #5293's "searchable" promise stays half-true.

Recommendation is 1, conditional on the reachability question this card most needs answered: is toSortItems used by any out-of-tree host at all? It is a documented export with zero in-tree production callers, so the honest answer is not derivable from this repo. Not a dev's own call either way — it is a published export's contract.

Dedup

Searched open issues (toSortItems, view-config-utils direction, tolerant dual-read sort spelling, plus the file path) — nothing on this. Related: #5293 (the views-prop rename that surfaced it, and which deliberately did not touch it), #4869 (the sort-sink convergence ruling quoted above).

Metadata

Metadata

Assignees

Labels

domain:uiobjectui ui stream: fix lands on the published library or apps — objectui execution seatpm:dispatched

Type

Projects

No projects

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions