morpheusgraphql / morpheus-graphql

Haskell GraphQL Api, Client and Tools
https://morpheusgraphql.com
MIT License
409 stars 63 forks source link

Failure on Resolving Field: Type mismatch! expected:List, got: null #667

Closed derrickbeining closed 2 years ago

derrickbeining commented 2 years ago

Context

# stack.yaml

extra-deps:
  - git: https://github.com/morpheusgraphql/morpheus-graphql.git
    commit: 1ad3b8d59a1e4f62628dfdcae204c768d2b5b0f7
    subdirs:
      - morpheus-graphql
      - morpheus-graphql-core
      - morpheus-graphql-code-gen
      - morpheus-graphql-app

Problem

I've got this resolver signature

tasks ::
  PGQ.MonadPostgres m =>
  GQL.Arg "pageSpec" (PageSpec Task OrderableAttribute Task.Uuid) ->
  GQL.Composed GQL.QUERY m [] Task

data OrderableAttribute
  = CreatedAt
  | StartTime
  | UpdatedAt
  deriving stock
    ( Eq
    , Generic
    , Show
    )
  deriving anyclass (GQL.GQLType)

The argument type is defined thus:

data PageSpec entity orderableAttr cursor = PageSpec
  { range :: Maybe Int
  , cursor :: cursor
  , orderBy :: OrderBy entity orderableAttr
  }
  deriving stock (Eq, Generic, Show)
  deriving anyclass (GQL.GQLType)

data OrderBy entity orderableAttr
  = OrderBy (Ordering entity orderableAttr) [Ordering entity orderableAttr]
  deriving stock
    ( Eq
    , Generic
    , Show
    )
  deriving anyclass (GQL.GQLType)

data Ordering object sortBy = Ordering
  { sortBy :: sortBy
  , direction :: Direction
  }
  deriving stock
    ( Eq
    , Generic
    , Show
    )
  deriving anyclass (GQL.GQLType)

data Direction
  = Asc
  | Desc
  | AscNullsFirst
  | DescNullsLast
  deriving stock
    ( Eq
    , Generic
    , Show
    )
  deriving anyclass (GQL.GQLType)

This produces this schema:

type Query {
  tasks(pageSpec: PageSpecTaskOrderableAttributeUuid!): [Task!]!
}

input PageSpecTaskOrderableAttributeUuid {
  range: Int
  cursor: TaskUuid!
  orderBy: OrderByTaskOrderableAttribute!
}

input OrderByTaskOrderableAttribute {
  _0: OrderingTaskOrderableAttribute!
  _1: [OrderingTaskOrderableAttribute!]!
}

input OrderingTaskOrderableAttribute {
  sortBy: OrderableAttribute!
  direction: Direction!
}

enum` OrderableAttribute {
  CreatedAt
  StartTime
  UpdatedAt
}

enum Direction {
  Asc
  Desc
  AscNullsFirst
  DescNullsLast
}

Now, when I attempt to query this resolver like so:

{
  tasks (
    pageSpec: {
      range: 100, 
      cursor:"fe4c0b39-17dc-47a2-8062-5b121181ef0b", 
      orderBy: {
        _0: {sortBy:CreatedAt, direction:Asc}
        _1: []
      }
    }
  )
  { ... }
}

I get this error:

Show / hide error message
```
{
  "errors": [
    {
      "message": "Failure on Resolving Field \"tasks\": Type mismatch! expected:List, got: null",
      "locations": [
        {
          "column": 3,
          "line": 12
        }
      ]
    },
    {
      "message": "Type mismatch! expected:InputObject, got: null. \n\nCurrent Type:\n--------------------------------------------------\n\nTask\n\n\n\nCurrent Selection:\n--------------------------------------------------\n\ntasks(pageSpec: { range: 100, cursor: \"fe4c0b39-17dc-47a2-8062-5b121181ef0b\", orderBy: { _0: { sortBy: CreatedAt, direction: Asc }, _1: [] } }) {\n  uuid\n  owner {\n    uuid\n  }\n}\n\n\n\nOperationDefinition:\n--------------------------------------------------\n\nquery {\n  organization(orgUuid: \"8e0a993e-89e0-490d-9f4b-889d10d9a22f\") {\n    uuid\n    name\n    createdAt\n    displayName\n    adminLabel\n    activatedBy {\n      uuid\n    }\n  }\n  tasks(pageSpec: { range: 100, cursor: \"fe4c0b39-17dc-47a2-8062-5b121181ef0b\", orderBy: { _0: { sortBy: CreatedAt, direction: Asc }, _1: [] } }) {\n    uuid\n    owner {\n      uuid\n    }\n  }\n}\n\n\n\n\nSchemaDefinition:\n--------------------------------------------------\n\nscalar OrganizationUuid\n\nscalar TaskUuid\n\nscalar UserUuid\n\nscalar UtcTimestamp\n\nenum Direction {\n  Asc\n  Desc\n  AscNullsFirst\n  DescNullsLast\n}\n\nenum OrderableAttribute {\n  CreatedAt\n  StartTime\n  UpdatedAt\n}\n\ninput OrderByTaskOrderableAttribute {\n  _0: OrderingTaskOrderableAttribute!\n  _1: [OrderingTaskOrderableAttribute!]!\n}\n\ninput OrderingTaskOrderableAttribute {\n  sortBy: OrderableAttribute!\n  direction: Direction!\n}\n\ninput PageSpecTaskOrderableAttributeUuid {\n  range: Int\n  cursor: TaskUuid!\n  orderBy: OrderByTaskOrderableAttribute!\n}\n\ntype Organization {\n  activatedAt: UtcTimestamp\n  activatedBy: User\n  active: Boolean!\n  adminLabel: String\n  availabilityCalendarActive: Boolean\n  brandingActive: Boolean!\n  createdAt: UtcTimestamp!\n  displayName: String\n  name: String!\n  updatedAt: UtcTimestamp!\n  uuid: OrganizationUuid!\n}\n\ntype Task {\n  uuid: TaskUuid!\n  owner: User\n}\n\ntype User {\n  uuid: UserUuid!\n}\n\ntype Query {\n  organization(orgUuid: OrganizationUuid!): Organization!\n  tasks(pageSpec: PageSpecTaskOrderableAttributeUuid!): [Task!]!\n}\n\n\n",
      "errorType": [],
      "locations": [
        {
          "column": 3,
          "line": 12
        }
      ]
    },
    {
      "message": "Type mismatch! expected:InputObject, got: null. \n\nCurrent Type:\n--------------------------------------------------\n\nTask\n\n\n\nCurrent Selection:\n--------------------------------------------------\n\ntasks(pageSpec: { range: 100, cursor: \"fe4c0b39-17dc-47a2-8062-5b121181ef0b\", orderBy: { _0: { sortBy: CreatedAt, direction: Asc }, _1: [] } }) {\n  uuid\n  owner {\n    uuid\n  }\n}\n\n\n\nOperationDefinition:\n--------------------------------------------------\n\nquery {\n  organization(orgUuid: \"8e0a993e-89e0-490d-9f4b-889d10d9a22f\") {\n    uuid\n    name\n    createdAt\n    displayName\n    adminLabel\n    activatedBy {\n      uuid\n    }\n  }\n  tasks(pageSpec: { range: 100, cursor: \"fe4c0b39-17dc-47a2-8062-5b121181ef0b\", orderBy: { _0: { sortBy: CreatedAt, direction: Asc }, _1: [] } }) {\n    uuid\n    owner {\n      uuid\n    }\n  }\n}\n\n\n\n\nSchemaDefinition:\n--------------------------------------------------\n\nscalar OrganizationUuid\n\nscalar TaskUuid\n\nscalar UserUuid\n\nscalar UtcTimestamp\n\nenum Direction {\n  Asc\n  Desc\n  AscNullsFirst\n  DescNullsLast\n}\n\nenum OrderableAttribute {\n  CreatedAt\n  StartTime\n  UpdatedAt\n}\n\ninput OrderByTaskOrderableAttribute {\n  _0: OrderingTaskOrderableAttribute!\n  _1: [OrderingTaskOrderableAttribute!]!\n}\n\ninput OrderingTaskOrderableAttribute {\n  sortBy: OrderableAttribute!\n  direction: Direction!\n}\n\ninput PageSpecTaskOrderableAttributeUuid {\n  range: Int\n  cursor: TaskUuid!\n  orderBy: OrderByTaskOrderableAttribute!\n}\n\ntype Organization {\n  activatedAt: UtcTimestamp\n  activatedBy: User\n  active: Boolean!\n  adminLabel: String\n  availabilityCalendarActive: Boolean\n  brandingActive: Boolean!\n  createdAt: UtcTimestamp!\n  displayName: String\n  name: String!\n  updatedAt: UtcTimestamp!\n  uuid: OrganizationUuid!\n}\n\ntype Task {\n  uuid: TaskUuid!\n  owner: User\n}\n\ntype User {\n  uuid: UserUuid!\n}\n\ntype Query {\n  organization(orgUuid: OrganizationUuid!): Organization!\n  tasks(pageSpec: PageSpecTaskOrderableAttributeUuid!): [Task!]!\n}\n\n\n",
      "errorType": [],
      "locations": [
        {
          "column": 3,
          "line": 12
        }
      ]
    }
  ]
}
```
  

However, if I replace the OrderBy type (isomorphic to non-empty list) with just a list, like

data PageSpec entity orderableAttr cursor = PageSpec
  { range :: Maybe Int
  , cursor :: cursor
  , orderBy :: [GQL.Ordering entity orderableAttr]
  }
  deriving stock (Eq, Generic, Show)
  deriving anyclass (GQL.GQLType)

And then try query the resolver again like so:

{
  tasks (
    pageSpec: {
      range: 100, 
      cursor:"fe4c0b39-17dc-47a2-8062-5b121181ef0b", 
      orderBy: [{sortBy:CreatedAt, direction:Asc}]
    }
  )
  { ... }
}

The the query resolves without any errors.

This seems like a bug, but I'm not exactly sure what is wrong. Have any ideas how to remedy my situation? My main goal is really to just be able to encode the orderBy field as something isomorphic to a non-empty list.

nalchevanidze commented 2 years ago

custom lists are not supported yet in Morpheus. it will be fixed by #666