Using X-Environment with GraphQL Client

Whilst using Dato environments I have hit an issue which I wasn’t sure how to circumvent when performing GraphQL queries scoped to an environment.

I’ve worked it out now and thought I would add it here in case anyone is wondering how to do it too.

Specifying works with the buildClient and the record is created and can be managed within the sandbox environment but when performing GraphQL queries the header option seems to be ignored (although I’m not sure if this is the case).

The environment can be specified in the buildClient by following the guidance in the documentation. It could look something like this:

import { buildClient } from '@datocms/cma-client-node'

const client = buildClient({
  apiToken: '<YOUR_TOKEN>',
  environment: 'staging',
})

For the GraphQL configuration you might have had something along these lines (use import syntax for ESM):

const { GraphQLClient } = require('graphql-request')

let endpoint = 'https://graphql.datocms.com/preview'

const graphQLClient = new GraphQLClient(endpoint, {
    headers: {
      authorization: `Bearer ${token}`,
      "Content-Type": 'application/json',
      "Accept": 'application/json',
      "X-Environment": "staging"
    },
})

const fetcher = await graphQLClient.request(queryString)

The package used to manage this might differ but the header will have to be supplied for authorization.

In the example above the endpoint is https://graphql.datocms.com/preview and the environment is passed as described in the documentation via headers. This will likely throw an error similar to this one:

[
  {
    "id": "aca3eb",
    "type": "api_error",
    "attributes": {
      "code": "INVALID_FIELD",
      "details": {
        "field": "suites",
        "field_id": "1696498",
        "field_label": "Suites",
        "field_type": "links",
        "errors": [
          "All records must belong to same environment"
        ],
        "code": "INVALID_FORMAT",
        "message": "Value not acceptable for this field type",
        "failing_value": [
          "17418716"
        ]
      }
    }
  }
]

The important part is All records must belong to same environment which essentially means the X-Environment header was ignored.

The way for this to work is to change the endpoint and specify the environment in the URL:

const { GraphQLClient } = require('graphql-request')

let endpoint = 'https://graphql.datocms.com/environments/staging/preview'

const graphQLClient = new GraphQLClient(endpoint, {
    headers: {
      authorization: `Bearer ${token}`,
      "Content-Type": 'application/json',
      "Accept": 'application/json',
    },
})

const fetcher = await graphQLClient.request(queryString)
1 Like