lighthouse icon indicating copy to clipboard operation
lighthouse copied to clipboard

Paginator return type is not applied to interface definition

Open tennox opened this issue 3 years ago • 6 comments

Describe the bug When creating an interface with a paginated field, the resulting schema definition is not transformed to an XPaginator.

Expected behavior/Solution The interface field should be transformed as well.

How to reproduce

interface Entity {
  field: [Return] @paginate
}
type EntityA {
  field: [Return] @paginate
}

Generated schema:

interface Entity {
  field: [Return]
}
type EntityA {
  field: ReturnPaginator
}

Lighthouse Version v4.18.0 (Is it possible this is fixed in v5? can't migrate yet)

Related: #936

tennox avatar Jan 25 '21 12:01 tennox

There are some complications to this that we have to consider:

interface Return {}

type ReturnA implements Return {}

interface Entity {
  field: [Return] @paginate
}

type EntityA implements Entity {
  field: [ReturnA] @paginate
}

What to do here?

spawnia avatar Jan 25 '21 13:01 spawnia

What to do here?

Good point. I think the defined type in the interface should be used (= ReturnPaginator). Only gotcha is that it needs to be generated if it doesn't exist anywhere else, but that logic exists already for types. This way the developer has most control and no smart logic is needed.

tennox avatar Jan 25 '21 16:01 tennox

I guess what needs to happen is that the generated paginator for the interface also becomes an interface, and the generated paginator for the implementing type will have to implement that interface.

interface Entity {
  field: ReturnPaginator
}

interface ReturnPaginator {
  data: [Return!]!
  paginatorInfo: PaginatorInfo!
}

type EntityA implements Entity {
  field: ReturnAPaginator
}

type ReturnAPaginator implements ReturnPaginator {
  data: [ReturnA!]!
  paginatorInfo: PaginatorInfo!
}

There might be cases where those interfaces could be omitted/folded together, but that would be more of a cosmetic optimisation. I think we should be good with that approach.

spawnia avatar Jan 25 '21 21:01 spawnia

Yeah that would also work. :+1:

tennox avatar Mar 13 '21 10:03 tennox

The same I think also applies to WhereConditions / OrderByClause:

interface Entity {
  field(
    where: _ @whereConditions
  ): ReturnPaginator
}

-> Error: Lighthouse failed while trying to load a type: _\n\nMake sure the type is present in your schema definition.

tennox avatar Mar 13 '21 10:03 tennox

Feel free to try your hands at a PR. Some pointers:

We need to allow directives to apply to interface fields as well as object type fields: https://github.com/nuwave/lighthouse/blob/ab80dd8f2b7697df1d85114670c7d23f04945a05/src/Schema/AST/ASTBuilder.php#L285

For backwards compatibility, let's make a new directive interface - similar to FieldManipulator - that accepts an InterfaceTypeDefinitionNode &$parentType: https://github.com/nuwave/lighthouse/blob/ab80dd8f2b7697df1d85114670c7d23f04945a05/src/Support/Contracts/FieldManipulator.php#L19

The existing field manipulator directives will have to be made aware that fields may have been defined on interfaces and manipulated there to cover the case outlined in https://github.com/nuwave/lighthouse/issues/1695#issuecomment-767134262

spawnia avatar Mar 15 '21 21:03 spawnia