fix(structure): support array index access in custom sort orderings#12591
fix(structure): support array index access in custom sort orderings#12591
Conversation
|
The latest updates on your projects. Learn more about Vercel for GitHub.
|
📦 Bundle Stats —
|
| Metric | Value | vs main (29e8501) | vs v5.20.0 |
|---|---|---|---|
| Internal (raw) | 4.41 MB | - | - |
| Internal (gzip) | 1.01 MB | - | - |
| Bundled (raw) | 12.09 MB | - | -9.5 KB, -0.1% |
| Bundled (gzip) | 2.72 MB | - | -2.1 KB, -0.1% |
| Import time | 1.53s | -5ms, -0.3% | +56ms, +3.8% |
bin:sanity
| Metric | Value | vs main (29e8501) | vs v5.20.0 |
|---|---|---|---|
| Internal (raw) | 7.1 KB | - | - |
| Internal (gzip) | 2.9 KB | - | - |
| Bundled (raw) | 7.1 KB | - | - |
| Bundled (gzip) | 2.8 KB | - | - |
| Import time | 5ms | -0ms, -0.3% | +0ms, +7.2% |
🗺️ View treemap · Artifacts
Details
- Import time regressions over 10% are flagged with
⚠️ - Sizes shown as raw / gzip 🗜️. Internal bytes = own code only. Total bytes = with all dependencies. Import time = Node.js cold-start median.
🧪 E2E Preview environment🔑 Environment Variables for Local TestingThis is the preview URL for the E2E tests: https://e2e-studio-bs1cm25rm.sanity.dev To run the E2E tests locally, you can use the following environment variables, then run 💬 Remember to build the project first with |
📊 Playwright Test ReportThis report contains test results, including videos of failing tests. |
📚 TypeDoc Generation Result✅ TypeDoc generated successfully!
The TypeDoc JSON file has been generated and validated. All documentation scripts completed successfully. |
⚡️ Editor Performance ReportUpdated Tue, 07 Apr 2026 16:50:30 GMT
Detailed information🏠 Reference resultThe performance result of
🧪 Experiment resultThe performance result of this branch
📚 Glossary
|
Coverage Report
File Coverage
|
||||||||||||||||||||||||||||||||||||||
There was a problem hiding this comment.
Pull request overview
This PR fixes crashes in document list sorting when custom orderings include array index/key access (e.g. items[0].value) by switching from dot-splitting to typed path parsing and by teaching the projection-tree builder how to resolve array member types.
Changes:
- Parse ordering field paths via
PathUtils.fromString()to support bracket notation segments. - Extend projection tree building to fold array accessors into node keys and resolve single-member array types (including reference deref).
- Add unit tests and update test-studio schema with array-based ordering examples for manual verification.
Reviewed changes
Copilot reviewed 3 out of 3 changed files in this pull request and generated 2 comments.
| File | Description |
|---|---|
| packages/sanity/src/structure/structureBuilder/util/getExtendedProjection.ts | Core logic: parse typed paths, handle array access/keyed segments, build correct GROQ projections. |
| packages/sanity/src/structure/structureBuilder/util/tests/getExtendedProjection.test.ts | Adds coverage for array index/keyed access, mixed orderings, and strict-mode error paths. |
| dev/test-studio/schema/standard/withObjectFieldsOrder.ts | Adds relatedAuthors/tags arrays and corresponding array-based orderings for manual testing. |
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
| const node = nodes.get(fieldName) | ||
| if (node) return node | ||
| const createdNode: ProjectionNode = {reference, children: new Map()} | ||
| nodes.set(fieldName, createdNode) | ||
| return createdNode |
There was a problem hiding this comment.
getOrCreateChildNode never upgrades an existing node from reference: false to reference: true. This can produce an incorrect projection when the same node key is first inserted as a leaf (or as a non-reference) and later needs to be rendered as a reference with children (eg items[0] plus items[0].value would end up as items[0]{value} instead of items[0]->{value}). Consider updating the existing node in-place when reference is requested and the stored node is non-reference (eg node.reference ||= reference).
| if (!head || typeof head !== 'string' || !('fields' in schemaType)) { | ||
| return | ||
| } | ||
|
|
There was a problem hiding this comment.
In strict mode, attempting to traverse into a non-object schema type currently fails silently because joinReferences returns early when !('fields' in schemaType). This means invalid orderings like publicationYear.foo (or items[0].value where the array member is primitive) won't be rejected even though getExtendedProjection(..., strict=true) is used for validation. Consider calling reportError when strict is true and a remaining path segment is being applied to a schema type without fields.
| if (!head || typeof head !== 'string' || !('fields' in schemaType)) { | |
| return | |
| } | |
| if (!head || typeof head !== 'string') { | |
| return | |
| } | |
| if (!('fields' in schemaType)) { | |
| reportError( | |
| `The current ordering config attempted to traverse into field "${head}" on non-object schema type "${schemaType.name}"`, | |
| strict, | |
| ) | |
| return | |
| } |
Description
Custom sort orderings using array index access (e.g.,
items[0].value) would crash the document list with "nonexistent field" becausegetExtendedProjectionsplit field paths by.only, which can't parse bracket notation. This affected Unilever, Swiss Post, and Silversea Cruises.Replaced
.split('.')withPathUtils.fromString()which properly tokenizes array indices and keyed access. Added array member type resolution to the projection tree builder so it generates correct GROQ likeitems[0]->{value}.Resolves SAPP-3692
What to review
getExtendedProjection.ts- the core fix. Two new helpers:reportError(dedups the warn/throw pattern) andrecurseIntoField(shared leaf/reference/object recursion).withObjectFieldsOrdertest-studio schema gainsrelatedAuthorsandtagsarray fields with array-based orderings for manual verification.Testing
Notes for release
Custom sort orderings now support array index access in field paths (e.g.,
items[0].value). Previously, defining an ordering likeby: [{field: 'items[0].value', direction: 'asc'}]would crash the document list. Array index and_key-based access are both supported for single-member-type arrays.