Skip to content

fix: pass dataType for orderBy entity queries#596

Merged
nikgraf merged 4 commits intomainfrom
fix/orderby-pass-datatype
Feb 27, 2026
Merged

fix: pass dataType for orderBy entity queries#596
nikgraf merged 4 commits intomainfrom
fix/orderby-pass-datatype

Conversation

@baiirun
Copy link
Contributor

@baiirun baiirun commented Feb 25, 2026

Summary

  • Pass dataType to entitiesOrderedByProperty for findManyPublic(..., { orderBy }) queries
  • Infer order-by data types from schema property metadata (string, number, boolean, date, point, schedule) and fail fast for unsupported fields
  • Add tests covering property-type to GraphQL dataType mapping used by ordered queries

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.
@nikgraf nikgraf merged commit 26cbcfc into main Feb 27, 2026
6 checks passed
@nikgraf nikgraf deleted the fix/orderby-pass-datatype branch February 27, 2026 05:52
@nikgraf nikgraf requested a review from Copilot February 27, 2026 05:52
Copy link
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

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 getOrderByDataType utility function to map property types to GraphQL dataType values
  • Modified findManyPublic to 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.

Comment on lines +75 to +95
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();
});
Copy link

Copilot AI Feb 27, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

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:

  1. Adding validation to throw an error when ordering by unsupported types (relations, backlinks, etc.), or
  2. 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.

Copilot uses AI. Check for mistakes.
Comment on lines +47 to +96
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();
});
});
Copy link

Copilot AI Feb 27, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

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.

Copilot uses AI. Check for mistakes.
Comment on lines +98 to +108
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();
});
});
Copy link

Copilot AI Feb 27, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

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.

Copilot uses AI. Check for mistakes.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants