diff --git a/src/nexusx/sdl_generator.py b/src/nexusx/sdl_generator.py index 48f6773..e60ea7b 100644 --- a/src/nexusx/sdl_generator.py +++ b/src/nexusx/sdl_generator.py @@ -358,7 +358,15 @@ def _generate_type(self, entity: type[SQLModel]) -> str: # Check if it's a relationship (references another entity) gql_type = self._type_hint_to_graphql(hint, entity, field_name) if gql_type: - fields.append(f" {field_name}: {gql_type}") + # Paginated list fields declare limit/offset args to match + # the introspection path — without them, SDL-only clients + # cannot tell the field is paginated. + if self._is_paginated_relationship(entity, field_name): + fields.append( + f" {field_name}(limit: Int, offset: Int = 0): {gql_type}" + ) + else: + fields.append(f" {field_name}: {gql_type}") # Build type definition with optional description type_def = f"type {entity.__name__} {{\n{chr(10).join(fields)}\n}}" diff --git a/tests/test_pagination_mixed.py b/tests/test_pagination_mixed.py index b72278c..3a63b01 100644 --- a/tests/test_pagination_mixed.py +++ b/tests/test_pagination_mixed.py @@ -87,7 +87,24 @@ def test_paginated_list_renders_as_result_type(self): assert "items: [SortedKid!]!" in sdl parent_block = sdl.split("type MixedParent {", 1)[1].split("}", 1)[0] - assert "sorted_kids: SortedKidResult!" in parent_block + # Field type is SortedKidResult! (non-null). Field may declare args + # — that's covered by test_paginated_field_exposes_limit_offset_args. + assert ": SortedKidResult!" in parent_block + + def test_paginated_field_exposes_limit_offset_args(self): + """Issue #85: paginated list field must declare limit/offset args in SDL. + + SDL and introspection must agree — without args in SDL, any client + that reads the schema via SDL (codegen tools, AI agents, GraphiQL + alternatives) cannot tell the field is paginated. + """ + registry = _make_registry() + sdl = SDLGenerator(MIXED_ENTITIES).generate( + enable_pagination=True, loader_registry=registry + ) + + parent_block = sdl.split("type MixedParent {", 1)[1].split("}", 1)[0] + assert "sorted_kids(limit: Int, offset: Int = 0): SortedKidResult!" in parent_block def test_non_paginated_list_renders_as_plain_list(self): """raw_kids (no order_by) → [RawKid!]! with no pagination args."""