mercurius-js / mercurius-gateway

Mercurius federation support plugin
MIT License
16 stars 11 forks source link

Error on array of entities extended #114

Open Drilmo opened 7 months ago

Drilmo commented 7 months ago

Hello,

I have an error on array of type extended.

I've modified the example found in the example directory, here's what I've done:

A post can be written by several authors, so in order to manage different authors per post and different posts per author I've created a link service that will centralize the modification of these links and allow a many-to-many relationship and avoid synchronization problems when adding or deleting authors and/or posts.

It has a database in format:

{
  l1: {
    lid:'l1',
    pid: 'p1',
    authorId: 'u1'
  },
  l2: {
    lid:'l2',
    pid: 'p2',
    authorId: 'u2'
  },
  l3: {
    lid:'l3',
    pid: 'p3',
    authorId: 'u1'
  },
  l4: {
    lid:'l4',
    pid: 'p4',
    authorId: 'u2'
  },
  l5: {
    lid:'l5',
    pid: 'p1',
    authorId: 'u2'
  },
  l6: {
    lid:'l6',
    pid: 'p3',
    authorId: 'u2'
  }
}

In this case, the schema will simply extend the existing schemas and allow you to obtain the list and number of posts per author and the list and number of authors per post.

Here's the schema:

type Post @key(fields: "pid") @extends {
        pid: ID! @external
        title: String @external
        authors: [User]
        numberOfAuthors: Int @requires(fields: "pid title")
      }

      type User @key(fields: "id") @extends {
        id: ID! @external
        name: String @external
        posts: [Post]
        numberOfPosts: Int @requires(fields: "id name")
      }

and here's the associated resolver:

{
      Post: {
        authors: post => {
            return Object.values(links).filter(l => l.pid === post.pid).map(link => {
                return {
                  __typename: 'User',
                  id: link.authorId
                }
              })
          },
        numberOfAuthors: post => {
            return Object.values(links).filter(l => l.pid === post.pid).length
          }
      },
      User: {
        posts: user => {
          return Object.values(links).filter(l => l.authorId === user.id).map(link => {
            return {
              __typename: 'Post',
              pid: link.pid
            }
          })
        },
        numberOfPosts: user => {
          return Object.values(links).filter(l => l.authorId === user.id).length
        }
      }
    }

However, when I run the following query :

query topPosts{
  topPosts(count:1){
    title
    authors{
      id
    }
    numberOfAuthors
  }
}

I get the result:

{
  "data": {
    "topPosts": [
      {
        "title": "Post 1",
        "authors": null,
        "numberOfAuthors": 2
      }
    ]
  },
  "errors": [
    {
      "message": "Unknown type \"Post\".",
      "locations": [
        {
          "line": 4,
          "column": 12
        }
      ]
    }
  ]
}

And the following log:

{
    "level": "INFO",
    "time": 1712305735959,
    "pid": 25416,
    "hostname": "localhost",
    "name": "mercurius-federation-sample",
    "reqId": "req-1",
    "err": {
        "type": "GraphQLError",
        "message": "Symbol(FEDERATED_ERROR)",
        "stack": "Error: Symbol(FEDERATED_ERROR)\n    at Object.sendRequest (C:\\xxx\\Git\\mercurius-gateway-sample\\node_modules\\.pnpm\\@mercuriusjs+gateway@3.0.0\\node_modules\\@mercuriusjs\\gateway\\lib\\gateway\\request.js:109:17)\n    at process.processTicksAndRejections (node:internal/process/task_queues:95:5)\n    at async C:\\Users\\xxx\\Git\\mercurius-gateway-sample\\node_modules\\.pnpm\\@mercuriusjs+gateway@3.0.0\\node_modules\\@mercuriusjs\\gateway\\lib\\gateway\\get-query-result.js:152:24\n    at async Promise.all (index 0)\n    at async fetchResult (C:\\xxx\\Git\\mercurius-gateway-sample\\node_modules\\.pnpm\\@mercuriusjs+gateway@3.0.0\\node_modules\\@mercuriusjs\\gateway\\lib\\gateway\\get-query-result.js:139:16)\n    at async typeToServiceMap.Query [as func] (C:\\xxx\\Git\\mercurius-gateway-sample\\node_modules\\.pnpm\\@mercuriusjs+gateway@3.0.0\\node_modules\\@mercuriusjs\\gateway\\lib\\gateway\\build-gateway.js:473:24)",
        "path": [
            "topPosts",
            0,
            "authors"
        ],
        "locations": [
            {
                "line": 35,
                "column": 5
            }
        ],
        "extensions": {
            "errors": [
                {
                    "message": "Unknown type \"Post\".",
                    "locations": [
                        {
                            "line": 4,
                            "column": 12
                        }
                    ]
                }
            ]
        }
    },
    "msg": "Symbol(FEDERATED_ERROR)"
}
{
    "level": "INFO",
    "time": 1712305735962,
    "pid": 25416,
    "hostname": "localhost",
    "name": "mercurius-federation-sample",
    "reqId": "req-1",
    "res": {
        "statusCode": 200
    },
    "responseTime": 38.72580003738403,
    "msg": "request completed"
}

And if I run the query :

query topUsers{
  topUsers(count:1){
    id
    posts{
      pid
      title
    }
    numberOfPosts
  }
}

I get the result:

{
  "data": {
    "topUsers": [
      {
        "id": "u1",
        "posts": null,
        "numberOfPosts": 2
      }
    ]
  },
  "errors": [
    {
      "message": "Unknown type \"User\".",
      "locations": [
        {
          "line": 4,
          "column": 12
        }
      ]
    }
  ]
}

And the following log:

{
    "level": "INFO",
    "time": 1712305974868,
    "pid": 39884,
    "hostname": "localhost",
    "name": "mercurius-federation-sample",
    "reqId": "req-1",
    "err": {
        "type": "GraphQLError",
        "message": "Symbol(FEDERATED_ERROR)",
        "stack": "Error: Symbol(FEDERATED_ERROR)\n    at Object.sendRequest (C:\\xxx\\Git\\mercurius-gateway-sample\\node_modules\\.pnpm\\@mercuriusjs+gateway@3.0.0\\node_modules\\@mercuriusjs\\gateway\\lib\\gateway\\request.js:109:17)\n    at process.processTicksAndRejections (node:internal/process/task_queues:95:5)\n    at async C:\\xxx\\Git\\mercurius-gateway-sample\\node_modules\\.pnpm\\@mercuriusjs+gateway@3.0.0\\node_modules\\@mercuriusjs\\gateway\\lib\\gateway\\get-query-result.js:152:24\n    at async Promise.all (index 0)\n    at async fetchResult (C:\\xxx\\Git\\mercurius-gateway-sample\\node_modules\\.pnpm\\@mercuriusjs+gateway@3.0.0\\node_modules\\@mercuriusjs\\gateway\\lib\\gateway\\get-query-result.js:139:16)\n    at async typeToServiceMap.Query [as func] (C:\\xxx\\Git\\mercurius-gateway-sample\\node_modules\\.pnpm\\@mercuriusjs+gateway@3.0.0\\node_modules\\@mercuriusjs\\gateway\\lib\\gateway\\build-gateway.js:473:24)",
        "path": [
            "topUsers",
            0,
            "posts"
        ],
        "locations": [
            {
                "line": 45,
                "column": 5
            }
        ],
        "extensions": {
            "errors": [
                {
                    "message": "Unknown type \"User\".",
                    "locations": [
                        {
                            "line": 4,
                            "column": 12
                        }
                    ]
                }
            ]
        }
    },
    "msg": "Symbol(FEDERATED_ERROR)"
}
{
    "level": "INFO",
    "time": 1712305974870,
    "pid": 39884,
    "hostname": "localhost",
    "name": "mercurius-federation-sample",
    "reqId": "req-1",
    "res": {
        "statusCode": 200
    },
    "responseTime": 40.68959999084473,
    "msg": "request completed"
}

Here's the code that reproduces this error: https://github.com/Drilmo/mercurius-gateway And run "exemple-2" to reproduce error

mcollina commented 7 months ago

Thanks for reporting! Would you like to send a Pull Request to address this issue? Remember to add unit tests.