Simplify your stack and build anything. Or everything.
Build tomorrow’s web with a modern solution you truly own.
Code-based nature means you can build on top of it to power anything.
It’s time to take back your content infrastructure.

Why does relationship return null in a custom GraphQL query?

default discord avatar
paulpopus2 years ago
4

This is what my query returns


{
  "data": {
    "GetCustomerOrders": {
      "docs": [
        {
          "id": "63edd88930491a91de039454",
          "createdAt": "2023-02-16T07:17:29.488Z",
          "paid": true,
          "product": null,
          "amount": 24000,
          "status": "IN_PROGRESS"
        }
      ]
    }
  }
}


This is the logic, basically inside my resolver



const orders = await payload.find({
    collection: 'orders',
    depth: 3,
    limit: 100,
    sort: '-createdAt',
    where: {
      'customer.value': {
        equals: customer.id,
      },
    },
    overrideAccess: true,
  })

  console.log('orders', orders.docs)

  return orders


And this is how my query is declared



export const GetCustomerOrders = (GraphQL: typeof ImportedGraphQL, payload: Payload) => {
  return {
    args: {},
    resolve: GetCustomerOrdersResolver,
    type: buildPaginatedListType('CustomerOrders', payload.collections['orders'].graphQL?.type),
  }
}


Product for some reason is returning

null

however in the console log, I can see that it's properly fetched via the local API.



product: { value: [Object], relationTo: 'products' },


This is a custom query for the

orders

collection type, if I use the generated query then it works fine so I'm struggling to figure out why this won't work.



Here's the query I'm testing in the playground:



query {
  GetCustomerOrders {
    docs {
      id
      createdAt
      paid
    product {
      value {
        ... on Product {
          title
        }
      }
    }
    amount
    status
    }
  }
}

^ this is same query works for the generated one 😫

  • discord user avatar
    jmikrut
    2 years ago

    so



    i am guessing this is because even though you are using the local API for your top-level query, and passing

    overrideAccess: true

    , you are still using the default

    orders

    GraphQL type that Payload builds



    and when you are querying on the field

    product

    , that is actually using Payload's internal GraphQL population method for retrieving the

    product

    field



    and that internal population method

    requires authentication

    basically even if your top-level resolver returns that data, because you are using an internal Payload GraphQL type, GraphQL will use

    Payload's internal field resolvers for relationship fields, requiring authentication
  • default discord avatar
    paulpopus2 years ago

    Interesting, the request is via authentication only. I basically want to recreate the generated "get orders" query but instead of having to pass a customer id into the query, I retrieve it from the req object so that 1. devex is easier and 2. theres no way to accidentally query other customer's orders even though in theory access control should handle that



    the product in this case is publically readable as well, i get customer id from req object and check a few details and then return the orders



    this is the full resolver


    interface ResolverArgs {}
    
    export const GetCustomerOrdersResolver = async (obj, args: ResolverArgs, { req }, info) => {
      const customer = req.user
    
      if (!customer.id) {
        throw new Error('Invalid user id')
      }
    
      if (customer.collection !== 'customers' || !customer._verified) {
        throw new Error('User could not be verified.')
      }
    
      const orders = await payload.find({
        collection: 'orders',
        depth: 3,
        limit: 100,
        sort: '-createdAt',
        where: {
          'customer.value': {
            equals: customer.id,
          },
        },
        overrideAccess: true,
      })
    
      return orders
    }


    but like you say it sounds like the resolver is not the issue



    in my request in the playground i'm passing a valid jwt token



    so when you say



    Payload's internal field resolvers for relationship fields, requiring authentication

    I played around with this more to try and figure it out but unfortunately I'm still stuck,

    @364124941832159242

    any ideas for a solution?

  • discord user avatar
    jmikrut
    2 years ago

    you should try passing the

    req

    or the

    user

    through to your

    payload.find

    it's still the resolver for sure. basically, you're saying give me orders with

    depth: 3

    but in reality, GraphQL doesn't care about if you ask for

    depth: 3

    or not, because it will handle population for each relationship itself



    so you should only do

    depth: 0

    there



    and let GraphQL handle the populations that you need for you via the built-in resolvers



    it may be due to

    depth: 3

    actually

  • default discord avatar
    paulpopus2 years ago

    🤦



    that was totally it, thanks a lot for the explanation



    the whole context ^ helps a lot for future issues as well

Star on GitHub

Star

Chat on Discord

Discord

online

Can't find what you're looking for?

Get dedicated engineering support directly from the Payload team.