fix: pass dataType for orderBy entity queries#596
Conversation
Ordered entity queries started returning empty results on testnet because entitiesOrderedByProperty now requires a dataType argument. The SDK was forwarding propertyId and sortDirection but not dataType, so orderBy calls silently returned no rows. This infers the GraphQL dataType from the schema property metadata, passes it with orderBy queries, and throws a clear error when an unsupported field is used for ordering. It also adds coverage for property-type to dataType mapping.
Keep passing inferred dataType when available, but allow orderBy queries to proceed without it so API-side fallback logic can resolve property types.
Make ordered queries include dataType only when it is resolvable, and avoid forcing a nullable dataType argument into every orderBy query. This keeps SDK behavior compatible with API fallback while preventing ambiguous null argument paths. Also add request-level tests for findManyPublic orderBy payload wiring and move mapping checks into a focused orderBy test suite.
There was a problem hiding this comment.
Pull request overview
This PR fixes orderBy entity queries by passing the dataType parameter to the entitiesOrderedByProperty GraphQL query. The fix infers data types from schema property metadata and passes them to the GraphQL API, which should improve query performance or correctness.
Changes:
- Added
getOrderByDataTypeutility function to map property types to GraphQL dataType values - Modified
findManyPublicto infer and pass dataType when building orderBy queries - Added comprehensive tests for dataType inference and orderBy query generation
Reviewed changes
Copilot reviewed 4 out of 4 changed files in this pull request and generated 3 comments.
| File | Description |
|---|---|
| packages/hypergraph/test/entity/find-many-public-orderby.test.ts | New test file covering orderBy with dataType parameter, testing both successful inference and cases where dataType cannot be resolved |
| packages/hypergraph/src/utils/convert-property-value.ts | Added getOrderByDataType function that maps property types to GraphQL dataType values with fallback to Schema keyword checks |
| packages/hypergraph/src/entity/find-many-public.ts | Integrated dataType inference into orderBy query building, conditionally including dataType parameter when available |
| .changeset/thirty-pumas-fix.md | Changeset marking this as a patch release for both hypergraph and hypergraph-react packages |
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
| it('omits dataType for unresolved orderBy field types', async () => { | ||
| await findManyPublic(Parent, { | ||
| space: 'space-1', | ||
| orderBy: { | ||
| property: 'children', | ||
| direction: 'asc', | ||
| }, | ||
| logInvalidResults: false, | ||
| }); | ||
|
|
||
| expect(mockRequest).toHaveBeenCalledTimes(1); | ||
| const [, queryDocument, queryVariables] = mockRequest.mock.calls[0]; | ||
|
|
||
| expect(queryDocument as string).not.toContain('$dataType: String'); | ||
| expect(queryDocument as string).not.toContain('dataType: $dataType'); | ||
| expect(queryVariables).toMatchObject({ | ||
| propertyId: CHILDREN_RELATION_PROPERTY_ID, | ||
| sortDirection: 'ASC', | ||
| }); | ||
| expect((queryVariables as Record<string, unknown>).dataType).toBeUndefined(); | ||
| }); |
There was a problem hiding this comment.
The PR description states "fail fast for unsupported fields" but the implementation doesn't actually fail when ordering by unsupported field types like relations. Instead, it silently omits the dataType parameter. Consider either:
- Adding validation to throw an error when ordering by unsupported types (relations, backlinks, etc.), or
- Updating the PR description to accurately reflect that unsupported types are handled by omitting the dataType parameter rather than failing fast.
This would make the behavior more predictable and consistent with the stated intent.
| describe('findManyPublic orderBy', () => { | ||
| beforeEach(() => { | ||
| mockRequest.mockReset(); | ||
| mockRequest.mockResolvedValue({ entities: [] }); | ||
| }); | ||
|
|
||
| it('passes inferred dataType for sortable fields', async () => { | ||
| await findManyPublic(Parent, { | ||
| space: 'space-1', | ||
| orderBy: { | ||
| property: 'score', | ||
| direction: 'desc', | ||
| }, | ||
| logInvalidResults: false, | ||
| }); | ||
|
|
||
| expect(mockRequest).toHaveBeenCalledTimes(1); | ||
| const [, queryDocument, queryVariables] = mockRequest.mock.calls[0]; | ||
|
|
||
| expect(queryDocument as string).toContain('$dataType: String'); | ||
| expect(queryDocument as string).toContain('dataType: $dataType'); | ||
| expect(queryVariables).toMatchObject({ | ||
| propertyId: SCORE_PROPERTY_ID, | ||
| dataType: 'float', | ||
| sortDirection: 'DESC', | ||
| }); | ||
| }); | ||
|
|
||
| it('omits dataType for unresolved orderBy field types', async () => { | ||
| await findManyPublic(Parent, { | ||
| space: 'space-1', | ||
| orderBy: { | ||
| property: 'children', | ||
| direction: 'asc', | ||
| }, | ||
| logInvalidResults: false, | ||
| }); | ||
|
|
||
| expect(mockRequest).toHaveBeenCalledTimes(1); | ||
| const [, queryDocument, queryVariables] = mockRequest.mock.calls[0]; | ||
|
|
||
| expect(queryDocument as string).not.toContain('$dataType: String'); | ||
| expect(queryDocument as string).not.toContain('dataType: $dataType'); | ||
| expect(queryVariables).toMatchObject({ | ||
| propertyId: CHILDREN_RELATION_PROPERTY_ID, | ||
| sortDirection: 'ASC', | ||
| }); | ||
| expect((queryVariables as Record<string, unknown>).dataType).toBeUndefined(); | ||
| }); | ||
| }); |
There was a problem hiding this comment.
Consider adding a test case for ordering by an optional property to ensure that the unwrapping logic in find-many-public.ts (lines 299-303) works correctly. This would cover schemas like Type.optional(Type.Number)('propertyId') to verify that the dataType is correctly inferred as 'float' even for optional fields.
| describe('getOrderByDataType', () => { | ||
| it('maps schema builder outputs to GraphQL order dataType values', () => { | ||
| expect(getOrderByDataType(Type.String('prop').ast)).toBe('text'); | ||
| expect(getOrderByDataType(Type.Number('prop').ast)).toBe('float'); | ||
| expect(getOrderByDataType(Type.Boolean('prop').ast)).toBe('boolean'); | ||
| expect(getOrderByDataType(Type.Date('prop').ast)).toBe('datetime'); | ||
| expect(getOrderByDataType(Type.Point('prop').ast)).toBe('point'); | ||
| expect(getOrderByDataType(Type.ScheduleString('prop').ast)).toBe('schedule'); | ||
| expect(getOrderByDataType(Type.Relation(Child)('prop').ast)).toBeUndefined(); | ||
| }); | ||
| }); |
There was a problem hiding this comment.
Consider adding a test case for ordering by a Backlink to verify the behavior is consistent with Relation types. Since Backlink wraps Relation internally, it should also return undefined for dataType, but this should be verified explicitly.
Summary
dataTypetoentitiesOrderedByPropertyforfindManyPublic(..., { orderBy })queriesstring,number,boolean,date,point,schedule) and fail fast for unsupported fieldsdataTypemapping used by ordered queries