Coder Social home page Coder Social logo

gatsby-source-craft's Introduction

Craft CMS + Gatsby

Gatsby source plugin for Craft CMS

This Gatsby source plugin provides an integration with Craft CMS. It uses Craft’s GraphQL API to make content within Craft available to Gatsby-powered front ends.

It requires Craft CMS 3.5.16 or later, and for the corresponding Gatsby Helper plugin 1.1.0 or later to be installed on the Craft site.

Currently, this plugin still downloads the queried Asset files locally using an older and more expensive approach that will be improved in a future release.


Table of Contents


Requirements

  • Craft CMS instance running with the Gatsby Helper plugin installed and configured.
  • Gatsby project you can work with locally.

Quick Start

Configure the Craft Helper Plugin

On the Craft CMS end, you’ll need the following:

  • Content in your Craft project that can be queried.
  • A configured GraphQL endpoint for Craft.
  • A GraphQL schema that has the Gatsby component enabled.

If you’ve never built a Craft site, the best place to start is the Intro to Craft CMS Tutorial.

For configuring Craft’s GraphQL endpoint, schema, and tokens, see Craft’s GraphQL documentation.

Once your endpoint and schema are established, be sure to enable Allow discovery of sourcing data for Gatsby in the Gatsby section of the schema you’d like to query with the gatsby-source-craft Gatsby plugin.

You may optionally designate a Preview webhook target URL in the plugin settings.

Install and Configure the Gatsby Source Plugin

1. Install the Source Plugin

Install the Gatsby source plugin by running the following command in your terminal:

# Gatsby 2
npm install --save-dev gatsby-source-craft@^1

# Gatsby 3
npm install --save-dev gatsby-source-craft

2. Configure the Source Plugin

You’ll need to provide Gatsby with access to Craft’s GraphQL endpoint. You can do this using CRAFTGQL_TOKEN and CRAFTGQL_URL in the Gatsby project’s .env file, or using the plugin setting’s craftGqlToken and craftGqlUrl options.

CRAFTGQL_TOKEN=your-graphql-token
CRAFTGQL_URL=https://your-craftcms-site.test/api
  // ...
  plugins: [
    {
      resolve: `gatsby-source-craft`,
      options: {
        craftGqlToken: `your-graphql-token`,
        craftGqlUrl: `https://your-craftcms-site.test/api`
      }
  ]
  // ...

You’ll also need to add the Gatsby source plugin in your gatsby-config.js file’s plugins array:

  // ...
  plugins: [
    `gatsby-source-craft`
  ]
  // ...

You may optionally override any of the default configuration options there as well:

  // ...
  plugins: [
    {
      resolve: `gatsby-source-craft`,
      options: {
        concurrency: 12,
        typePrefix: `CraftGQL_`
      }
  ]
  // ...

3. Confirm Success

Run gatsby develop and you should be able to watch Gatsby source the entire Craft CMS schema. When it’s finished, you should be able to query your Craft content running http://localhost:8000/___graphql.

Now you’re ready to query Craft CMS content and build a blazing-fast Gatsby front end!

Overview

Craft’s flexible content schema is accessible to front ends via Element Queries and a similar public GraphQL API. This Gatsby source plugin, combined with its companion Craft CMS plugin, translates your Craft project schema specifically for Gatsby’s internal GraphQL API.

Diagram of Craft CMS via source plugin to private Gatsby GraphQL

Gatsby uses source plugins like this to collect content from any number of sources (local markdown, REST and GraphQL APIs, etc.) and combine them in a single, consistent GraphQL API that can be used to build a React-based front end.

If you’re a hands-on learner, the quickest way to appreciate the difference between these GraphQL APIs is to see each in action. Open GraphiQL from the Craft control panel and run gatsby develop before visiting http://localhost:8000/___graphql. Gatsby’s GraphQL API is the one you’ll query when building your Gatsby site.

If you’re a learn-by-reading type that’s new to Craft CMS, you may first want to look at Craft’s GraphQL API see how you’d fetch content directly. It’ll probably help make sense of the schema available to Gatsby. If you’re new to Gatsby, the Gatsby Tutorials offer an excellent start with the basics.

💡 Tip: take a look at the Craft CMS Blog Starter if you’d like to see an example Craft+Gatsby integration that uses this source plugin.

Usage

Configuration Options

Option Default Description
concurrency 10 Number of concurrent connections to use querying Craft.
craftGqlUrl null Craft GraphQL API endpoint URL. Used, if not defined by an environment variable.
craftGqlToken null Craft GraphQL API access token. Used, if not defined by an environment variable.
debugDir .cache/craft-graphql-documents Directory for storing generated GraphQL documents for debugging.
fragmentsDir .cache/craft-fragments Directory for storing GraphQL fragments.
typePrefix Craft_ Craft schema type prefix. (Underscore is optional; see examples below.)
looseInterfaces false Whether to allow filtering all Craft types by all available interfaces. (See Enabling Loose Interfaces.)
sourcingParams {} Parameters to be included by type when sourcing content. (See Using Sourcing Parameters)
enabledSites null Defaults to primary site, but may be set to an array of site handles. (See Sourcing Multiple Sites.)
fetchOptions null Options passed to node-fetch when executing a request to the API.)
retryOptions { retries: 1 } Options passed to p-retry on API requests. Allows for automatic retries if a request fails (e.g. due to temporary network failure, server timeout, etc...).)

Fetching Craft Content

Once your Craft CMS content schema has been sourced and translated into Gatsby data nodes, you’ll query those nodes from your Gatsby components.

If you’re new to Gatsby, this is a vital and potentially confusing distinction: you’ll query Gatsby’s GraphQL API in your React components, and that’s different from Craft’s GraphQL API.

The examples that follow assume you’re using the default Craft_ type prefix. If you’ve specified a different one, like Foo_ for example, the types in your queries would change slightly.

typePrefix: 'Craft_' typePrefix: 'Foo_'
Craft_blog_blog_Entry Foo_blog_blog_Entry
allCraftBlogBlogEntry allFooBlogBlogEntry
craftBlogBlogEntry fooBlogBlogEntry

You’ll be able to query content to get either a single object or several of them that are returned in a nodes array. You can narrow the kind of content you’d like in two different ways:

  1. As a specific element type, like a blog section and entry type.
  2. As a generic content type, meaning content that may exist across different sections and entry types.

Specific element types will be accessible via allCraft<camelCasedGraphQLType> and craft<camelCasedGraphQLType>. For example, a Blog section and entry type would be available as allCraftBlogBlogEntry and craftBlogBlogEntry. Whether you’re dealing with one object or several, you won’t need to further specify each node’s type to query its custom content fields.

# multiple blog post entry titles + custom field values
{
  allCraftBlogBlogEntry {
    nodes {
      title
      myCustomBlogField
    }
  }
}
# single blog post entry title + custom field values
{
  craftBlogBlogEntry {
    title
    myCustomBlogField
  }
}

💡 Why BlogBlog instead of Blog?
The first Blog refers to the Craft section type while the second refers to the entry type. Often there’s just a single entry type per section, but there can be many of them!

Generic content types will be accessible via allCraft<interfaceName> and craft<interfaceName>. You’ll likely have, for example, allCraftEntryInterface and craftEntryInterface. These can fetch GraphQL objects that implement the Entry interface. In other words, entries that may exist in different sections and entry types.

# multiple entry titles with custom *blog* field values
{
  allCraftEntryInterface {
    nodes {
      title
      ... on Craft_blog_blog_Entry {
        myCustomBlogField
      }
    }
  }
}
# single entry title with custom *blog* field value
{
  craftEntryInterface {
    title
    ... on Craft_blog_blog_Entry {
      myCustomBlogField
    }
  }
}

Different filters will be available depending on how you query content, and the quickest way to see what’s there is to open Gatsby’s GraphiQL interface (usually at http://localhost:8000/___graphql) and explore.

To query generic content types and select only blog channel entries, which would achieve the same result as the first example, you could do the following:

# multiple entry titles with custom *blog* field values, but ... only from the blog
{
  allCraftBlogBlogEntry(filter: {sectionHandle: {eq: "blog"}}) {
    nodes {
      title
      ... on Craft_blog_blog_Entry {
        myCustomBlogField
      }
    }
  }
}

Keep in mind that the id you’ll receive for each object is Gatsby-specific. The element ID you’d be used to working with in Craft will be on the remoteId property instead.

The following query, for example...

{
  craftBlogBlogEntry {
    title
    id
    remoteId
    remoteTypeName
  }
}

...might return...

{
  "data": {
    "craftBlogBlogEntry": {
      "title": "Post One",
      "id": "blog_blog_Entry:10",
      "remoteId": "10",
      "remoteTypeName": "blog_blog_Entry"
    }
  }
}

...where 10 is the entry ID as you’d refer to it in Craft CMS. Similarly, Craft’s typename will be available as remoteTypeName.

Gatsby offers a nice tutorial on using GraphQL to build your site: https://www.gatsbyjs.com/docs/graphql/

Enabling Loose Interfaces

⚠️ This is an experimental setting that allows deviation from an otherwise strict specification. Use at your own risk!

When looseInterfaces is enabled, the source plugin will add all fields to the GraphQL interfaces that are implemented by at least one of the GraphQL types. This allows for vastly more filterable queries to the detriment of clarity and readability for each specific type.

For example: if your entries are books, bicycles, and birds, you’ve probably customized fields/properties that make immediate sense with looseInterfaces disabled:

  • books
    • isbn
    • price
  • bicycles
    • numGears
    • price
  • birds
    • beakShape
    • nestingLocation

As you encounter each type via the GraphQL API, you’ll see those properties as they’re presented above—but when querying generic content types you’ll only be able to limit your search by books, bicycles, and/or birds.

With looseInterfaces enabled, each result object will list the properties available across all types. The benefit is you can further limit the query scope by a more specific property. You might search all objects by price, for example, and end up with books and bicycles as results.

  • books
    • isbn
    • price
    • numGears
    • beakShape
    • nestingLocation
  • bicycles
    • isbn
    • price
    • numGears
    • beakShape
    • nestingLocation
  • birds
    • isbn
    • price
    • numGears
    • beakShape
    • nestingLocation

The downside is that each result may be more confusing to look at. Birds will have ISBNs, bicycles will have nesting locations, and books will have beak shapes—which does not reflect the nature of reality. The actual content does not change and the value of each irrelevant field would be null, but each type would include every other type’s properties.

This is only true for interfaces that share a specific type, not all interfaces in Craft’s schema. In more practical terms, a normal section entry could have a misleading structureId property—but an asset would not.

⚠️ Filtering by a non-existent field can result in unexpected behavior. Make sure your other filter fields narrow the results down to a set of results that actually implement the field you’re filtering against.

Using Sourcing Parameters

You can use the sourcingParams config option to pass additional GraphQL query parameters when the Craft CMS site is sourced by this plugin. You might use these parameters, for example, to fetch disabled or expired entries since they’re not available by default.

The option takes an object where each key represents the source type you’d like to extend with an object of parameters to be included when sourcing that type.

This example limits assets fetched from the uploads volume to images only, and sets archived: false on all Asset sourcing queries:

{
  resolve: `gatsby-source-craft`,
  options: {
    sourcingParams: {
      uploads_Asset: {
        kind: '"image"'
      },
      AssetInterface: {
        archived: "false"
      }
    }
  }
}

Sourcing Multiple Sites

By default, only your primary Craft CMS site will be sourced for Gatsby. You can enable additional sites, however, using the enabledSites config option.

This example directs the plugin to source content from the default site and a second French site—assuming default is the default site’s handle and french is the handle for the second site.

{
  resolve: `gatsby-source-craft`,
  options: {
    enabledSites: [`default`, `french`]
  }
}

Live Preview

For Local Development

In order to support live preview targets for Craft content editors, Gatsby must be running in development mode and the Craft CMS Gatsby Helper must be configured with the Gatsby development server’s URL.

  1. In the Craft control panel, add a new live preview target that points to your desired Gatsby URL. (For example: http://localhost:8000/blog/{slug}. Leave Refresh un-checked.)
  2. In the Craft control panel, navigate to SettingsGatsby Helper and be sure you’ve added your Preview webhook target URL pointing to your local Gatsby site. (Working locally, this will most likely be http://localhost:8000/__refresh.)
  3. In your Gatsby project, edit .env to include ENABLE_GATSBY_REFRESH_ENDPOINT = true.
  4. Run or restart gatsby develop.

You should now be able to select your Gatsby preview target in live preview and see content updates automatically applied in the preview pane.

⚠️ Gatsby does not support rendering a page on its own. When you save a draft during the live preview, Gatsby rebuilds the entire site using the draft instead of the entry itself. Craft does its best to tell Gatsby when to rebuild the site again without using the draft, but it is possible that a site remains built with a draft instead of the published entry.

For Production

We recommend Gatsby Cloud for live preview in production.

Configure a site to provide a CMS Preview in Gatsby Cloud:

  1. From your Cloud workspace, choose Add a site +.
  2. Select Import from a Git repository, choose your GitHub or GitLab account, and designate the repository, branch, base directory, and site name you’d like to use.
  3. When you reach Integrations, choose Skip this step.
  4. Complete the Setup step by adding your CRAFTGQL_TOKEN, CRAFTGQL_URL, and ENABLE_GATSBY_REFRESH_ENDPOINT to both the Build variables and Preview variables.
  5. Wait for the first builds to complete, then grab settings for the Craft configuration steps below:
    • Navigate to Site Settings and grab the Preview Webhook.
    • Navigate to CMS Preview and copy the *.gtsb.io base URL.

Configure Craft CMS to use Gatsby Cloud for live preview:

  1. Add a new live preview target that uses your Gatsby Cloud CMS Preview URL. (For example: https://preview-foo1234.gtsb.io/blog/{slug}. Leave Refresh un-checked.)
  2. Navigate to SettingsGatsby Helper and add the webhook URL from step #5 above to the Preview webhook target URL field. (This will look like https://webhook.gatsbyjs.com/hooks/data_source/xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx, without the __refresh part you would add for local development.)

You should now be able to select your Gatsby preview target in live preview and see content updates automatically applied in the preview pane.

💡 You can set the Preview webhook target URL field to an environment variable like $GATSBY_PREVIEW_WEBHOOK to manage it more easily across environments.

Building the Site

Gatsby sites are built by querying source nodes and processing the results.

💡 If you’re new to Gatsby, be sure to read up on how to build a site using source plugins.

Once data from any source, including Craft CMS, is converted into Gatsby data nodes, you’ll query those data nodes against Gatsby’s internal storage rather than the original source. The GraphQL queries you write in your Gatsby components will query Gatsby’s data nodes and not the Craft CMS GraphQL API.

When a build process is launched, the plugin will query the Craft site to understand what content is available. It then checks the fragments directory and uses any already cached there to speed things up. If a given part of the schema is not already represented by a cached fragment, one will be generated and saved instead.

Once everything’s cached on this first run, subsequent builds will apply delta changes and be much faster. (If Craft’s project config is changed or you run gatsby clean, the entire site will be sourced again.)

Customizing Generated Fragments

Fragments are standard GraphQL speak for reusable chunks of GraphQL queries.

You can utilize fragments to help make your Gatsby project components more DRY. The source plugin uses them as a way of caching what’s often a complex Craft CMS content schema.

By default, Gatsby will fetch everything from Craft. That doesn’t mean all your site’s content is displayed, but that Gatsby fully catalogs the schema so it can be available to use however and wherever you’d like within your Gatsby components.

Because fetching the entire schema is expensive, and because hand-writing schema fragments would be tedious and overwhelming, the source plugin’s strategy is to generate fragments for you—including Gatsby-specific fields and aliases—and save them locally to speed up subsquent builds.

💡 If you haven’t specified your own fragmentsDir config setting, you’ll find autogenerated fragments in the node_modules/gatsby-source-craft/.cache/craft-fragments/ directory.

Once those fragments are generated, you can edit them down by hand to remove anything you don’t want to be available. You can also remove them all—which is easiest using gatsby clean to have them fully regenerated in the next build process.

You can customize these sourced fragments in two ways:

  1. Appending your own fragments to be included with the build.
  2. Directly editing those cached source fragments for full control.

Either way you’ll want to start by specifying a fragmentsDir config option to point to a path within your Gatsby project. Changes you make there will be copied into node_modules/gatsby-source-craft/.cache/craft-fragments/ at build time, overwriting anything that’s there. Keeping fragmentsDir separate ensures customizations won’t be lost when running gatsby clean and re-sourcing the Craft schema.

Appending Custom Fragments

To add your own fragments to the sourced schema, create a file ending in .graphql and add your custom fragment.

If we set a custom fragmentsDir of craft-fragments, for example, and we want to add a custom square image to our blog entries, we might create a craft-fragments/blogImages.graphql file and add the following:

fragment thumbnailImage on blog_blog_Entry {
  coverImage {
    square: url @transform (width: 300 height: 300)
  }
}

This will be copied into node_modules/gatsby-source-craft/.cache/craft-fragments/ at build time and used as Gatsby’s source nodes are built—meaning coverImage will be available on blog entries with its URL to a 300px square image.

Editing Sourced Fragments

For complete control over the sourced schema, you can copy any of the generated types into your fragmentsDir.

cp node_modules/gatsby-source-craft/.cache/craft-fragments/blog_blog_Entry.graphql craft-fragments/blog_blog_Entry.graphql

In this case it’s important to maintain the exact filename of the type fragment you’d like to override. This allows you to remove properties you don’t want available to Gatsby, apply directives by default on existing ones, and change the auto-generated fragment however you’d like.

The only downside is that you’re fully overriding the source fragment and you’ll need to manually apply any future Craft schema changes yourself; running gatsby clean and re-sourcing the Craft schema will generate an up-to-date fragment in node_modules/gatsby-source-craft/.cache/craft-fragments/, but it will be ignored since you’re overriding it.

Applying Directives

The most common scenario for adjusting the generated fragments is for creating custom fields or applying directives. Since directives are applied when Craft returns the data, they cannot be applied after Gatsby already has it. The same is true for applying filters that only Craft would know how to process.

See Craft’s list of available GraphQL directives for more on what’s available.

Using image transforms, for example, would require generating them when sourcing the data. Here we’ve modified the custom frontPageThumb asset field to specifically return a URL for an image pre-cropped to 400 pixels square:

fragment uploads_Asset on uploads_Asset {
  remoteId: id
  uid
  title
  slug
  enabled
  url
  frontPageThumb: url(width: 400, height: 400)
}

Differences from Other Source Plugins

gatsby-source-graphql

Most Gatsby-Craft sites were likely built with the gatsby-source-graphql plugin, which executes GraphQL queries at build time. This comes with two main disadvantages:

  1. Because every GraphQL query is executed at build time, builds could be slow particularly with larger sites.
  2. Every build is all-or-nothing, with no ability to partially source schema changes.

This Craft CMS Gatsby source plugin is tailored for optimal utilization of Craft’s content schema. It first sources all the data from the Craft site via its native GraphQL API, then converts everything into Gatsby data nodes. The complete schema is sourced into locally-cached fragments that speed up subsequent builds, so only schema changes need to be queried and sourced.

If you’re migrating a Gatsby project from the GraphQL source plugin to this Craft CMS source plugin, you’ll need to adjust your configuration and make some changes to your queries. They should generally be cleaner and slightly more concise:

  • Queries will no longer need to be wrapped by the source handle. (query { craft {} }query {}.)
  • Multi-object queries will take the form of allCraft*, while single-object queries will start with craft* and no longer need to specify a type when a single section/entry type is queried.
  • Queries for multiple objects (like allCraft*) will return results in a nodes array.
  • Craft’s search parameter is no longer available as a filter. It was a convenient hack for querying specific field values and relationships, both of which may be done more cleanly using this source plugin.
  • References to any element’s id should be remoteId instead.
  • Any user details, like entry author information, must be wrapped with ... on Craft_User {}.
  • Various casing will need to change, often from snake case (blog_blog_Entry) to camelCase (BlogBlogEntry). Only fragments continue to use snake case, like ... on Craft_blog_blog_Entry {}.

gatsby-source-craftcms

Despite having a similar name, the legacy gatsby-source-craftcms plugin is unaffiliated with this one, and is now deprecated.

Integrating Third-Party Content

By default, this plugin only exposes elements provided by Craft itself. You can use your own custom module or third-party plugin to add elements using the following events:

registerSourceNodeTypes

Event that’s triggered when registering source node types.

Plugins get a chance to specify additional elements that should be Gatsby source nodes.

use craft\gatsbyhelper\events\RegisterSourceNodeTypesEvent;
use craft\gatsbyhelper\services\SourceNodes;
use yii\base\Event;

Event::on(
    SourceNodes::class,
    SourceNodes::EVENT_REGISTER_SOURCE_NODE_TYPES,
    function(RegisterSourceNodeTypesEvent $event) {
        $event->types[] = [
            'node' => 'book',
            'list' => 'books',
            'filterArgument' => 'type',
            'filterTypeExpression' => '(.+)_Book',
            'targetInterface' => BookInterface::getName(),
        ];
    }
);

Defining source node types looks a bit complex, so let’s go over the definition line-by-line:

  • node is the GraphQL query Gatsby should use when querying for a single node. This must match the query name provided by your plugin.
  • list is the GraphQL query Gatsby should use when querying for a list of nodes. This must match the query name provided by your plugin.
  • filterArgument is the argument name to be used when querying for distinct types.
    When querying for assets, for example, it would be volume where entries would be type. This is necessary for elements that have different types. If your element does not, you can leave this blank.
  • filterTypeExpression is used with filterArgument to figure out the value for the argument. The value of this will be applied as a regular expression to the GraphQL type name of a specific element and the first returned match will be used as the value.
    For example, for assets the value is (.+)_Asset$ while for entries the value is (?:.+)_(.+)_Entry+$ (because we need to use the entry type handle, not section handle).
  • targetInterface is the GraphQL interface name to which the node type configuration should be applied.

registerIgnoredTypes

Event that’s triggered when registering ignored element types.

Plugins get a chance to specify which element types should not be updated individually.

use craft\gatsbyhelper\events\RegisterIgnoredTypesEvent;
use craft\gatsbyhelper\services\Deltas;
use yii\base\Event;

Event::on(
    Deltas::class,
    Deltas::EVENT_REGISTER_IGNORED_TYPES,
    function(RegisterIgnoredTypesEvent $event) {
        $event->types[] = MyType::class;
    }
);

This event should be used for element types that will always be updated as part of a different element. For example, a Matrix block will never be updated by itself—it will always be updated when saving some other element, so the changes to individual Matrix blocks should not be tracked.

Troubleshooting

Gatsby doesn’t see Craft schema changes.

When you add new fields, Gatsby will pull in only the content it’s told to query—whatever is specified in the GraphQL fragments. You either have to add the new fields to the already-existing fragments or you can simply clear out the fragment folder so that Gatsby regenerates them on the next run.

Subsequent Gatsby builds have incomplete content.

When you run Gatsby subsequently, if Gatsby caches have not been cleaned out, Gatsby will only query Craft for changes since the last time Gatsby queried for content. This is called incremental sourcing and it helps reduce the data transferred between Gatsby and Craft. It also helps Gatsby re-build its data node store.

As new data is pulled in, though, Gatsby might not know all the relations made by Craft and also which relations might be used when building the site. (See the related issue here). This means that sometimes incremental sourcing can make your site have some obsolete content. For this reason, it is recommended to do a full page build (by cleaning the Gatsby caches beforehand) before deploying the built site.

childImageSharp nodes result in an error.

Craft image assets can be fetched by URL and transformed by Craft, but cannot yet be transformed easily with gatsby-image. See the following issue for current status and a workaround: #6

Resources

We highly recommend you check out these resources as you’re getting started with Craft CMS and Gatsby:

gatsby-source-craft's People

Contributors

andris-sevcenko avatar brandonkelly avatar kara-todd avatar kije avatar mattstein avatar monachilada avatar snyk-bot avatar wardpeet avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

gatsby-source-craft's Issues

"gatsby-source-craft" threw an error while running the sourceNodes lifecycle

Description

I'm getting this error when running two sites with diffrent URL’s. The main site should be headless, the second site got some minor functions where I’m using Crafts CMS' templating engine.

After setting up the second site my GatsbyJS site wont build anymore and I’m getting this error. The only workaround so far is to run “garsby clean”. after making an update or changes on entries.

ERROR #11321  PLUGIN
"gatsby-source-craft" threw an error while running the sourceNodes lifecycle:

Cannot read property 'map' of null

  488 |         // Create the sourcing node events
  489 |         const nodeEvents = [
> 490 |             ...updatedNodes.map(entry => {
      |                             ^
  491 |                 return {
  492 |                     eventName: 'UPDATE',
  493 |                     remoteTypeName: entry.nodeType,

File: node_modules/gatsby-source-craft/gatsby-node.js:490:29

  TypeError: Cannot read property 'map' of null
  
  - gatsby-node.js:490 Object.exports.sourceNodes
    [stm-web]/[gatsby-source-craft]/gatsby-node.js:490:29
  
  - task_queues:96 processTicksAndRejections
    node:internal/process/task_queues:96:5
  
  - api-runner-node.js:432 runAPI
    [stm-web]/[gatsby]/src/utils/api-runner-node.js:432:16

Steps to reproduce

  1. Setup Craft with multiple sites, don't share the sections
  2. Run gatsby develop
  3. Add a page
  4. Refresh data

Additional info

  • Craft version: 3.7.15
  • PHP version: 7.3.31
  • Database driver & version: MySQL 5.6.51
  • Plugins & versions:
  • Cloner: 1.2.2
  • Gatsby Helper: 1.0.5
  • Redactor: 2.8.8
  • Smith: 1.1.14
  • Spoon: 3.6.1
  • Sprout Notes: 2.2.3
  • Tags: 1.0.8

Unknown argument "status" on field "asset" of type "Query"

Description

I upgraded to v1.02 and received the following error upon build (Gatsby Cloud & locally):

Screen Shot 2021-05-26 at 8 54 39 PM

Steps to reproduce

  1. Update to version v1.02
  2. npm run build

Additional info

  • Craft version: 3.6.15
  • PHP version: 7.4.11
  • Database driver & version: MySQL 5.7.30
  • Plugins & versions:
    • aelvan/mailchimp-subscribe: 3.0.3
    • craftcms/commerce: 3.3.2
    • craftcms/commerce-stripe: 2.3.2.1
    • craftcms/gatsby-helper: 1.0.1
    • craftcms/redactor: 2.8.7
    • nystudio107/craft-seomatic: 3.3.42
    • putyourlightson/craft-amazon-ses: 1.3.3
    • vaersaagod/matrixmate: 1.2.7
    • verbb/super-table: 2.6.8

I can provide Craft project config/composer.json/database if required.

Add support to Gatsby v4

Description

The plugin runs in dev mode, just throwing:

warn Plugin gatsby-source-craft is not compatible with your gatsby version 4.0.0 - It requires gatsby@^3.0.0

But when I try to build, I get:

success onPostBootstrap - 0.136s
info bootstrap finished - 30.937s
success write out requires - 0.007s

 ERROR #11321  PLUGIN

"gatsby-source-craft" threw an error while running the createSchemaCustomization lifecycle:

ENOENT: no such file or directory, open '/Code/craftcms-gatsby-website/node_modules/
gatsby-source-craft/.cache/craft-graphql-documents/home_home_Entry.graphql'



  Error: ENOENT: no such file or directory, open '/Code/craftcms-gatsby-website/node
  _modules/gatsby-source-craft/.cache/craft-graphql-documents/home_home_Entry.graphql'


 ERROR #11321  PLUGIN

"gatsby-source-craft" threw an error while running the createSchemaCustomization lifecycle:

ENOENT: no such file or directory, open '/Code/craftcms-gatsby-website/node_modules/
gatsby-source-craft/.cache/craft-graphql-documents/home_home_Entry.graphql'



  Error: ENOENT: no such file or directory, open '/Code/craftcms-gatsby-website/node
  _modules/gatsby-source-craft/.cache/craft-graphql-documents/home_home_Entry.graphql'


 ERROR #11321  PLUGIN

"gatsby-source-craft" threw an error while running the createSchemaCustomization lifecycle:

ENOENT: no such file or directory, open '/Code/craftcms-gatsby-website/node_modules/
gatsby-source-craft/.cache/craft-graphql-documents/home_home_Entry.graphql'



  Error: ENOENT: no such file or directory, open '/Code/craftcms-gatsby-website/node
  _modules/gatsby-source-craft/.cache/craft-graphql-documents/home_home_Entry.graphql'


 ERROR

UNHANDLED REJECTION Worker exited before finishing task



  Error: Worker exited before finishing task

  - index.js:112 ChildProcess.<anonymous>
    [craftcms-gatsby-website]/[gatsby-worker]/dist/index.js:112:45

  - child_process.js:282 Process.ChildProcess._handle.onexit
    internal/child_process.js:282:12


not finished Building production JavaScript and CSS bundles - 2.184s

error Command failed with exit code 1.
info Visit https://yarnpkg.com/en/docs/cli/run for documentation about this command.

Steps to reproduce

  1. Have Craft running on Nitro
  2. Build Gatsby Site that

Additional info

  • Craft version: 3.7.17.1

  • Nitro version: 2.0.8

  • PHP version: 8.0.11

  • Database driver & version: MySQL 5.7.33

  • Plugins & versions:

    • Expanded Singles 1.1.4
    • Gatsby Helper 1.0.7
    • Imager X v3.5.3
    • Navigation 1.4.21
    • Redactor 2.8.8
    • SEOmatic 3.4.17
    • Super Table 2.6.8
    • Typed link field 1.0.25
  • Gatsby version: 4.0

    • gatsby-source-craft version: 2.0.4
{
  resolve: `gatsby-source-craft`,
  options: {
    fragmentsDir: `${__dirname}/craft-fragments/`,
    debugDir: `${__dirname}/craft-debug/`,
    craftGqlToken: process.env.CRAFTGQL_TOKEN,
    craftGqlUrl: process.env.CRAFTGQL_URL,
    typePrefix: `Craft_`,
  },
},

changes are ignored when using multiple sites

Using multiple sites:
When changing an entry in Craft CMS. GatsbyJS dosn’t make the changes. I have to preform a "gatsby clean” to see my changes. Turn the extra site off and it will build.

@andris-sevcenko

Steps to reproduce

  • Save entry
  • run "gatsby build"
  • turn it off the extra site and the page will build

Additional info

  • Craft version: 3.7.16
  • PHP version: 7.3.31
  • Database driver & version: MySQL 5.6.51
  • Plugins & versions:
  • Cloner: 1.2.2
  • Gatsby Helper: 1.0.6
  • Redactor: 2.8.8
  • Formie: 1.4.21.1
  • Smith: 1.1.14
  • Spoon: 3.6.1
  • Sprout Notes: 2.2.3
  • Tags: 1.0.9

GraphQL error after installing Formie plugin

Description

Installing Formie throws the following error. We have tried enabling all "Formie" related checkboxes under GQL schema settings but we won't use that, anyway enabling them just throws another error. If we disable Formie the error goes away.

success fetching Form - 12.772s

 ERROR #11330  PLUGIN

"gatsby-source-craft" threw an error while running the sourceNodes lifecycle:

Variable "$id" is not defined

  468 |     if (remoteConfigVersion !== localConfigVersion || !localContentUpdateTime) {
  469 |         reporter.info("Cached content is unavailable or outdated, sourcing _all_ nodes.");
> 470 |         await sourceAllNodes(config);
      |         ^
  471 |     }
  472 |     else {
  473 |         reporter.info(`Craft config version has not changed since last sourcing. Checking for content changes since "${localContentUpdateTime}".`);

Make sure that you don't have a typo somewhere and use valid arguments in sourceNodes lifecycle.
Learn more about sourceNodes here: https://www.gatsbyjs.com/docs/reference/config-files/gatsby-node/#sourceNodes

File: node_modules/gatsby-source-craft/gatsby-node.js:470:9

success Checking for changed pages - 0.001s

This is the error with all checkboxes enabled under "Formie" in the GraphQL settings.

 ERROR #11321  PLUGIN

"gatsby-node.js" threw an error while running the createPages lifecycle:

Interface field Craft_FormInterface.fields expected but Craft_Form does not provide it.

  4 |   const { createPage } = actions
  5 |
> 6 |   const result = await graphql(`
    |                        ^
  7 |     query {
  8 |       allCraftPagesStandardEntry {
  9 |         nodes {

File: gatsby-node.js:6:24



  Error: Interface field Craft_FormInterface.fields expected but Craft_Form does not provide it.

Steps to reproduce

  1. Install Formie
  2. Run "gatsby develop"

Additional info

  • Craft version: 3.7.16
  • PHP version: 7.3.31
  • Database driver & version: MySQL 5.6.51
  • Plugins & versions:
    Cloner | 1.2.2
    Formie | 1.4.20
    Gatsby Helper | 1.0.5
    Redactor | 2.8.8
    Smith | 1.1.14
    Spoon | 3.6.1
    Sprout Notes | 2.2.3
    Tags | 1.0.9

Querying fixed, fluid, or gatsbyImage nodes of the childImageSharp node of a Craft asset results in an error.

Description

The gatsby-source-craft plugin makes childImageSharp nodes appear in Gatsby's GraphiQL interface, but querying any of the fields within the fixed, fluid, or gatsbyImage nodes results in the following error:

The "path" argument must be of type string or an instance of Buffer or URL. Received undefined

Steps to reproduce

  1. install and configure gatsby-source-craft
  2. run gatsby develop
  3. open GraphiQL on http://localhost:8000/___graphql and query any fields within the fixed, fluid, or gatsbyImage nodes of the childImageSharp of a Craft CMS asset such as:
... on Craft_EXAMPLE_Asset {
  childImageSharp {
    gatsbyImageData(layout: FLUID)
  }
}

Additional info

  • Craft version: Craft Pro 3.5.15.1
  • PHP version: 7.3.19
  • Database driver & version: MySQL 5.5.5
  • Plugins & versions: Gatsby 1.0.0-beta.1

Missing entries in Gatsby GraphQL

Description

From a total of 5,059 entries, only 2993 are making it from Craft to Gatsby. I've tracked the issue down to duplicate nodes being created by gatsby-graphql-source-toolkit. So (to the sum of exactly the the number of missing entries) one to several remoteNodes with the same id/same fields are passed to the createNodes function, hence losing around 2000 out of my total. The entries have unique ids/data in Craft and I can't spot any rhyme nor reason why some are overwritten by duplicates.

I'm still trying to figure out exactly why this is happening but the GraphiQL playground in the Craft Admin seems to return all the correct entries and the 'gatsby-source-craft` plugin attempts to create 5,069 nodes when building the Gatsby GraphQL layer, it's just overwriting 2000 of them.

Any guidance or help on my next steps to get to the root of the problem would be most appreciated. I'm currently investigating the fragments being built at the start of the process.

Additional info

  • Craft version: 3.5.18
  • Plugins & versions:
    Gatsby Helper - 1.0.0-beta.2
    gatsby-source-craft - 1.0.0-beta.2

Random number of entries returned

Hi!

We have one entry type with 279 entries that returns a completely random number of entries when queried from Gatsby. Craft´s built in GraphiQL always returns all 279. We can run gatsby develop and get 133, then run gatsby clean, run gatsby develop again and get 200, 179, 249 and so on. Completely random. This data in Craft is imported from a CSV file using Feed Me. I have cleared all caches in Craft and also re-saved all entries using the CLI and tried disabling / enabling all those entries.

This also happens when running gatsby build, we added a console.log to show the number of entries in the build log.

Any ideas what we are missing or how to debug this issue?

Moving elements in structures causes partial updates with incremental builds

Description

I have a structure section used to create a sidebar and page hierarchy. The sidebar hierarchy doesn't update or gets out of order when moving nodes and doing incremental builds.

I've determined that moving a structure item does not update the Element's dateUpdated so it is not picked up in the nodesUpdatedSince list.

This is compounded by the fact that if I then edit one of the structure entries, only the edited entry will feed through to nodesUpdatedSince and I end up with invalid lft/rgt values in the structure in the Gatsby internal storage.

Here's my solution that I've used to get around this issue... you may have a different take on the issue or a different direction to take it so it's just here for reference:

flowsa/gatsby-helper@93e9425

    public function getUpdatedNodesSinceTimeStamp(string $timestamp): array
    {
        $structureUpdates = (new Query())
            ->select(['elementId', 'structureId'])
            ->from([CraftTable::STRUCTUREELEMENTS])
            ->andWhere(['>', 'dateUpdated', Db::prepareDateForDb($timestamp)])
            ->pairs();

        return (new Query())
            ->select(['id', 'type'])
            ->from([CraftTable::ELEMENTS])
            ->where(['dateDeleted' => null])
            ->andWhere(['not in', 'type', $this->_getIgnoredTypes()])
            ->andWhere(
                ['or',
                    ['>', 'dateUpdated', Db::prepareDateForDb($timestamp)],
                    ['IN', 'id', array_keys($structureUpdates)]
                ]
            )
            ->andWhere(['revisionId' => null])
            ->andWhere(['draftId' => null])
            ->pairs();
    }

Using Neo field with more than one level returns null value on Gatsby GraphQL

Description

Trying to query gatsby graphql data on any neo field that has more than one level will return null value.

Steps to reproduce

  1. Create a new Neo field with the following Level 0, Level 1, Level 2, having Level 1 as an allow child block of level 0 and Level 2 as an allow child block of Level 1

Screen Shot 2022-10-31 at 1 35 41 PM

Screen Shot 2022-10-31 at 1 35 52 PM

Screen Shot 2022-10-31 at 1 36 03 PM

  1. Create an entry that utilizing this field.

Screen Shot 2022-10-31 at 1 37 52 PM

  1. Go to Gatsby GraphQL to try to query the level 2's content, they are not available.

Screen Shot 2022-10-31 at 1 40 15 PM

Additional info

  • Craft version: 3.7.57
  • PHP version: 7.4.30
  • Database driver & version: MySQL 8.0.30
  • Plugins & versions: Neo - 2.13.15

Register custom types

Description

I assume you have already thought about this, but what is the plan for custom element types and other custom GraphQL types?

crash on netlify deploy after adding new content

Description

I'm getting a periodic failed build on Netlify – it seems to happen after a new piece of content is added, but it's not happening consistently. If I clear the cache and rebuild on Netlify, the problem goes away. But here's what's reported in the logs:

4:50:38 PM: error "gatsby-source-craft" threw an error while running the sourceNodes lifecycle:
4:50:38 PM: Node "event_event_Entry" with id "[object Object]" is nullish.
4:50:38 PM:   510 |         }
4:50:38 PM:   511 |         // And source, if needed
4:50:38 PM: > 512 |         await sourceNodeChanges(config, { nodeEvents });
4:50:38 PM:       |         ^
4:50:38 PM:   513 |     }
4:50:38 PM:   514 |     await cache.set(`CRAFT_CONFIG_VERSION`, remoteConfigVersion);
4:50:38 PM:   515 |     await cache.set(`CRAFT_LAST_CONTENT_UPDATE`, remoteContentUpdateTime);
4:50:39 PM: 
4:50:39 PM: 
4:50:39 PM:   Error: Node "event_event_Entry" with id "[object Object]" is nullish.
4:50:40 PM: Failed during stage 'building site': Build script returned non-zero exit code: 2
4:50:39 PM:   
4:50:39 PM:   - fetch-nodes.ts:21 Object.fetchNonNullishNodesById
4:50:39 PM:     [repo]/[gatsby-graphql-source-toolkit]/src/source-nodes/fetch-nodes/fetch-no    des.ts:21:13
4:50:39 PM:   
4:50:39 PM:   - create-nodes.ts:13 Object.createNodes
4:50:39 PM:     [repo]/[gatsby-graphql-source-toolkit]/src/source-nodes/node-actions/create-    nodes.ts:13:20
4:50:39 PM:   
4:50:39 PM:   - async Promise.all
4:50:39 PM:   
4:50:39 PM:   - source-node-changes.ts:35 sourceNodeChanges
4:50:39 PM:     [repo]/[gatsby-graphql-source-toolkit]/src/source-nodes/source-node-changes.    ts:35:3
4:50:39 PM:   
4:50:39 PM:   - gatsby-node.js:512 Object.exports.sourceNodes
4:50:39 PM:     [repo]/[gatsby-source-craft]/gatsby-node.js:512:9
4:50:39 PM:   
4:50:39 PM:   - api-runner-node.js:485 runAPI
4:50:39 PM:     [repo]/[gatsby]/src/utils/api-runner-node.js:485:16
4:50:39 PM:   
4:50:39 PM: 
4:50:39 PM: not finished source and transform nodes - 4.251s

There what seems to have happened is that a user added a new entry of content type Event, but this doesn't seem to be tied to any particular content type; and this error always goes away when I clear the cache on Netlify.

I am running the Gatsby Cache plugin on Netlify, and it's possible that's getting in the way of things – I like it because it does bring build times down considerably, but I'm going to try to turn it off to see if it's contributing to this error.

Steps to reproduce

  1. Add new piece of content
  2. Try to redeploy
  3. . . . and sometimes this happens? But not always!

Additional info

  • Craft version: Craft Pro 3.6.11.2
  • PHP version: 7.2.24
  • Database driver & version: MySQL 5.5.5
  • Plugins & versions:

Gatsby Helper 1.0.1
nethooks 1.1.2
Redactor 2.8.5
Webhooks 2.3.2

Missing onError handler for invocation 'building-schema' error

Description

Hey There,

So I just installed gatsby-source-craft and when I ran gatsby develop, I ran into the following error

Missing onError handler for invocation 'building-schema', error was 'Error: Cannot resolve types for CraftGQL_games_games_Entry'. Stacktrace was 'Error: Cannot resolve types for
CraftGQL_games_games_Entry
    at resolveInterfaceArrayAsThunk (/Users/me/Documents/Web-Stuff/Public/giochi-react/node_modules/graphql-compose/lib/utils/configAsThunk.js:102:11)
    at ObjectTypeComposer.getInterfaces (/Users/me/Documents/Web-Stuff/Public/giochi-react/node_modules/graphql-compose/lib/ObjectTypeComposer.js:734:84)
    at mergeTypes (/Users/me/Documents/Web-Stuff/Public/giochi-react/node_modules/gatsby/src/schema/schema.js:371:10)
    at forEach (/Users/me/Documents/Web-Stuff/Public/giochi-react/node_modules/gatsby/src/schema/schema.js:287:11)
    at Array.forEach (<anonymous>)
    at addTypes (/Users/me/Documents/Web-Stuff/Public/giochi-react/node_modules/gatsby/src/schema/schema.js:246:9)
    at updateSchemaComposer (/Users/me/Documents/Web-Stuff/Public/giochi-react/node_modules/gatsby/src/schema/schema.js:135:9)
    at buildSchema (/Users/me/Documents/Web-Stuff/Public/giochi-react/node_modules/gatsby/src/schema/schema.js:62:9)
    at build (/Users/me/Documents/Web-Stuff/Public/giochi-react/node_modules/gatsby/src/schema/index.js:105:24)
    at buildSchema (/Users/me/Documents/Web-Stuff/Public/giochi-react/node_modules/gatsby/src/services/build-schema.ts:19:3)'

right after this error it seems to hang on building schema.

I have run gatsby clean a number of times, deleted my .cache folder to no avail.

Additional info

  • Craft version: Craft Pro 3.5.17.1

  • PHP version: 7.4.7

  • Database driver & version: MySQL 5.7.32

  • Plugins & versions:
    Amazon S3 1.2.11
    Feed Me 4.3.4
    Gatsby Helper 1.0.0-beta.2
    Imager X v3.2.6
    Navigation 1.4.12
    Redactor 2.8.5
    Scout 2.1.4
    SEOmatic 3.3.29

  • npmPackages:
    fontawesome-pro 5.14.0
    fontawesome-svg-core 1.2.30
    mdx 1.6.22
    @popmotion/popcorn 0.4.4
    @robinmetral/gatsby-source-s3 2.1.1
    algoliasearch 4.8.3
    babel-plugin-styled-components 1.12.0
    framer-motion 2.6.7
    gatsby 2.24.49
    gatsby-plugin-mdx 1.9.0
    gatsby-plugin-react-helmet 3.8.0
    gatsby-plugin-sharp 2.12.1
    gatsby-plugin-styled-components 3.8.0
    gatsby-source-craft 1.0.0-beta.2
    gatsby-source-filesystem 2.9.0
    gatsby-source-graphql 2.12.0
    gatsby-transformer-sharp 2.10.1
    polished 3.6.5
    react 16.13.1
    react-alice-carousel 2.2.1
    react-autosuggest 10.1.0
    react-dom 16.13.1
    react-helmet 6.1.0
    react-instantsearch-dom 6.8.2
    react-rating 2.0.5
    react-tooltip 4.2.8
    styled-components 5.1.1

I am not exactly sure what could be causing this as I can pull the data using the gatsby-source-graphql plugin.

Updated nodes not populated on build

Description

When a "non-clean" Gatsby build occurs, we always receive the following error.

"gatsby-source-craft" threw an error while running the sourceNodes lifecycle:

Cannot read properties of null (reading 'map')

  488 |         // Create the sourcing node events
  489 |         const nodeEvents = [
> 490 |             ...updatedNodes.map(entry => {
      |                             ^
  491 |                 return {
  492 |                     eventName: 'UPDATE',
  493 |                     remoteTypeName: entry.nodeType,

File: node_modules/gatsby-source-craft/gatsby-node.js:490:29



  TypeError: Cannot read properties of null (reading 'map')
  
  - gatsby-node.js:490 Object.exports.sourceNodes
    [frankie004-gatsby]/[gatsby-source-craft]/gatsby-node.js:490:29
  
  - task_queues:96 processTicksAndRejections
    node:internal/process/task_queues:96:5
  
  - api-runner-node.js:432 runAPI
    [frankie004-gatsby]/[gatsby]/src/utils/api-runner-node.js:432:16

The following is an extract from out web.log file:

2021-11-17 10:48:57 [-][-][-][error][GraphQL\Error\Error] String cannot represent value: []
2021-11-17 10:48:57 [-][-][-][error][GraphQL\Error\Error] String cannot represent value: []
2021-11-17 10:48:57 [-][-][-][info][application] Request body:{
  "query": "query NODE_footerSecondary_Node($id: [QueryArgument], $siteId: [QueryArgument]) {\n  node(id: $id, siteId: $siteId, status: null) {\n    remoteTypeName: __typename\n    ..._CraftfooterSecondary_NodeID_\n    ...footerSecondary_Node\n  }\n}\n\nquery LIST_footerSecondary_Node($limit: Int, $offset: Int) {\n  nodes(limit: $limit, offset: $offset, site: \"default\") {\n    remoteTypeName: __typename\n    ..._CraftfooterSecondary_NodeID_\n    ...footerSecondary_Node\n  }\n}\n\nfragment _CraftfooterSecondary_NodeID_ on footerSecondary_Node {\n  remoteTypeName: __typename\n  remoteId: id\n  siteId\n}\n\nfragment footerSecondary_Node on footerSecondary_Node {\n  remoteId: id\n  uid\n  title\n  slug\n  uri\n  enabled\n  archived\n  siteId\n  siteSettingsId\n  language\n  searchScore\n  trashed\n  status\n  dateCreated\n  dateUpdated\n  lft\n  rgt\n  level\n  root\n  structureId\n  elementId\n  navId\n  navHandle\n  navName\n  type\n  classes\n  urlSuffix\n  customAttributes {\n    remoteTypeName: __typename\n    ... on NodeCustomAttribute {\n      attribute\n      value\n    }\n  }\n  data\n  newWindow\n  url\n  nodeUri\n  remoteChildren: children {\n    remoteTypeName: __typename\n    remoteId: id\n    siteId\n  }\n  remoteParent: parent {\n    remoteTypeName: __typename\n    remoteId: id\n    siteId\n  }\n  element {\n    remoteTypeName: __typename\n    ... on Element {\n      ... on Element {\n        id\n        uid\n        title\n        slug\n        uri\n        enabled\n        archived\n        siteId\n        siteSettingsId\n        language\n        searchScore\n        trashed\n        status\n        dateCreated\n        dateUpdated\n      }\n    }\n    ... on home_home_Entry {\n      sourceId\n      siteId\n    }\n    ... on flexibleContent_heroCards_BlockType {\n      ... on flexibleContent_heroCards_BlockType {\n        id\n        uid\n        title\n        slug\n        uri\n        enabled\n        archived\n        siteId\n        siteSettingsId\n        language\n        searchScore\n        trashed\n        status\n        dateCreated\n        dateUpdated\n        fieldId\n        ownerId\n        typeId\n        typeHandle\n        sortOrder\n        columns\n        centreText\n        cards {\n          remoteTypeName: __typename\n          ... on cards_BlockType {\n            id\n            uid\n            title\n            slug\n            uri\n            enabled\n            archived\n            siteId\n            siteSettingsId\n            language\n            searchScore\n            trashed\n            status\n            dateCreated\n            dateUpdated\n            fieldId\n            ownerId\n            typeId\n            sortOrder\n            heading\n            body\n            headingLink {\n              remoteTypeName: __typename\n              ... on linkField_Link {\n                ariaLabel\n                customText\n                element {\n                  remoteTypeName: __typename\n                  ... on Element {\n                    remoteTypeName: __typename\n                  }\n                  ... on home_home_Entry {\n                    sourceId\n                    siteId\n                  }\n                  ... on flexibleContent_heroCards_BlockType {\n                    remoteTypeName: __typename\n                  }\n                  ... on cards_BlockType {\n                    remoteTypeName: __typename\n                  }\n                  ... on flexibleContent_textAndImages_BlockType {\n                    remoteTypeName: __typename\n                  }\n                  ... on flexibleContent_imageBanner_BlockType {\n                    remoteTypeName: __typename\n                  }\n                  ... on flexibleContent_servicesCarousel_BlockType {\n                    remoteTypeName: __typename\n                  }\n                  ... on flexibleContent_features_BlockType {\n                    remoteTypeName: __typename\n                  }\n                  ... on flexibleContent_featuresPanel_BlockType {\n                    remoteTypeName: __typename\n                  }\n                  ... on flexibleContent_featureCards_BlockType {\n                    remoteTypeName: __typename\n                  }\n                  ... on flexibleContent_video_BlockType {\n                    remoteTypeName: __typename\n                  }\n                  ... on flexibleContent_callToAction_BlockType {\n                    remoteTypeName: __typename\n                  }\n                  ... on flexibleContent_careProfessionals_BlockType {\n                    remoteTypeName: __typename\n                  }\n                  ... on flexibleContent_budgetGraph_BlockType {\n                    remoteTypeName: __typename\n                  }\n                  ... on flexibleContent_reviewsCarousel_BlockType {\n                    remoteTypeName: __typename\n                  }\n                  ... on reviews_BlockType {\n                    remoteTypeName: __typename\n                  }\n                  ... on flexibleContent_textBlock_BlockType {\n                    remoteTypeName: __typename\n                  }\n                  ... on flexibleContent_partnerCards_BlockType {\n                    remoteTypeName: __typename\n                  }\n                  ... on partners_BlockType {\n                    remoteTypeName: __typename\n                  }\n                  ... on flexibleContent_bCorp_BlockType {\n                    remoteTypeName: __typename\n                  }\n                  ... on flexibleContent_pricing_BlockType {\n                    remoteTypeName: __typename\n                  }\n                  ... on levelCard_BlockType {\n                    remoteTypeName: __typename\n                  }\n                  ... on flexibleContent_contentColumns_BlockType {\n                    remoteTypeName: __typename\n                  }\n                  ... on textColumns_BlockType {\n                    remoteTypeName: __typename\n                  }\n                  ... on flexibleContent_accordionPanel_BlockType {\n                    remoteTypeName: __typename\n                  }\n                  ... on items_BlockType {\n                    remoteTypeName: __typename\n                  }\n                  ... on flexibleContent_leadHeading_BlockType {\n                    remoteTypeName: __typename\n                  }\n                  ... on flexibleContent_leadText_BlockType {\n                    remoteTypeName: __typename\n                  }\n                  ... on flexibleContent_serviceDetail_BlockType {\n                    remoteTypeName: __typename\n                  }\n                  ... on rows_BlockType {\n                    remoteTypeName: __typename\n                  }\n                  ... on serviceDetailColumns_column_BlockType {\n                    remoteTypeName: __typename\n                  }\n                  ... on flexibleContent_subscriptionForm_BlockType {\n                    remoteTypeName: __typename\n                  }\n                  ... on flexibleContent_currentStatus_BlockType {\n                    remoteTypeName: __typename\n                  }\n                  ... on flexibleContent_informationGrid_BlockType {\n                    remoteTypeName: __typename\n                  }\n                  ... on flexibleContent_contactUs_BlockType {\n                    remoteTypeName: __typename\n                  }\n                  ... on options_BlockType {\n                    remoteTypeName: __typename\n                  }\n                  ... on flexibleContent_linkCards_BlockType {\n                    remoteTypeName: __typename\n                  }\n                  ... on serviceCategories_default_Entry {\n                    sourceId\n                    siteId\n                  }\n                  ... on pages_flexibleContent_Entry {\n                    sourceId\n                    siteId\n                  }\n                  ... on searchResults_searchResults_Entry {\n                    sourceId\n                    siteId\n                  }\n                  ... on pages_basic_Entry {\n                    sourceId\n                    siteId\n                  }\n                  ... on flexibleContentBasic_richText_BlockType {\n                    remoteTypeName: __typename\n                  }\n                  ... on flexibleContentBasic_image_BlockType {\n                    remoteTypeName: __typename\n                  }\n                  ... on servicesIndex_servicesIndex_Entry {\n                    sourceId\n                    siteId\n                  }\n                  ... on newsIndex_newsIndex_Entry {\n                    sourceId\n                    siteId\n                  }\n                  ... on newsArticle_default_Entry {\n                    sourceId\n                    siteId\n                  }\n                  ... on eventsIndex_eventsIndex_Entry {\n                    sourceId\n                    siteId\n                  }\n                  ... on eventsArticle_default_Entry {\n                    sourceId\n                    siteId\n                  }\n                  ... on serviceItems_default_Entry {\n                    sourceId\n                    siteId\n                  }\n                  ... on newsCategories_default_Entry {\n                    sourceId\n                    siteId\n                  }\n                  ... on images_Asset {\n                    remoteId: id\n                    siteId\n                  }\n                  ... on icons_Asset {\n                    remoteId: id\n                    siteId\n                  }\n                  ... on User {\n                    remoteId: id\n                    siteId\n                  }\n                  ... on General_GlobalSet {\n                    remoteId: id\n                    siteId\n                  }\n                  ... on seo_GlobalSet {\n                    remoteId: id\n                    siteId\n                  }\n                  ... on main_Node {\n                    remoteId: id\n                    siteId\n                  }\n                  ... on footerPrimary_Node {\n                    remoteId: id\n                    siteId\n                  }\n                  ... on footerSecondary_Node {\n                    remoteId: id\n                    siteId\n                  }\n                }\n                target\n                text\n                title\n                type\n                url\n              }\n            }\n            image {\n              remoteTypeName: __typename\n              remoteId: id\n              siteId\n            }\n            signatureName\n            signatureText\n            signatureTextLink {\n              remoteTypeName: __typename\n              ... on linkField_Link {\n                ariaLabel\n                customText\n                element {\n                  remoteTypeName: __typename\n                  ... on Element {\n                    remoteTypeName: __typename\n                  }\n                  ... on home_home_Entry {\n                    sourceId\n                    siteId\n                  }\n                  ... on flexibleContent_heroCards_BlockType {\n                    remoteTypeName: __typename\n                  }\n                  ... on cards_BlockType {\n                    remoteTypeName: __typename\n                  }\n                  ... on flexibleContent_textAndImages_BlockType {\n                    remoteTypeName: __typename\n                  }\n                  ... on flexibleContent_imageBanner_BlockType {\n                    remoteTypeName: __typename\n                  }\n                  ... on flexibleContent_servicesCarousel_BlockType {\n                    remoteTypeName: __typename\n                  }\n                  ... on flexibleContent_features_BlockType {\n                    remoteTypeName: __typename\n                  }\n                  ... on flexibleContent_featuresPanel_BlockType {\n                    remoteTypeName: __typename\n                  }\n                  ... on flexibleContent_featureCards_BlockType {\n                    remoteTypeName: __typename\n                  }\n                  ... on flexibleContent_video_BlockType {\n                    remoteTypeName: __typename\n                  }\n                  ... on flexibleContent_callToAction_BlockType {\n                    remoteTypeName: __typename\n                  }\n                  ... on flexibleContent_careProfessionals_BlockType {\n                    remoteTypeName: __typename\n                  }\n                  ... on flexibleContent_budgetGraph_BlockType {\n                    remoteTypeName: __typename\n                  }\n                  ... on flexibleContent_reviewsCarousel_BlockType {\n                    remoteTypeName: __typename\n                  }\n                  ... on reviews_BlockType {\n                    remoteTypeName: __typename\n                  }\n                  ... on flexibleContent_textBlock_BlockType {\n                    remoteTypeName: __typename\n                  }\n                  ... on flexibleContent_partnerCards_BlockType {\n                    remoteTypeName: __typename\n                  }\n                  ... on partners_BlockType {\n                    remoteTypeName: __typename\n                  }\n                  ... on flexibleContent_bCorp_BlockType {\n                    remoteTypeName: __typename\n                  }\n                  ... on flexibleContent_pricing_BlockType {\n                    remoteTypeName: __typename\n                  }\n                  ... on levelCard_BlockType {\n                    remoteTypeName: __typename\n                  }\n                  ... on flexibleContent_contentColumns_BlockType {\n                    remoteTypeName: __typename\n                  }\n                  ... on textColumns_BlockType {\n                    remoteTypeName: __typename\n                  }\n                  ... on flexibleContent_accordionPanel_BlockType {\n                    remoteTypeName: __typename\n                  }\n                  ... on items_BlockType {\n                    remoteTypeName: __typename\n                  }\n                  ... on flexibleContent_leadHeading_BlockType {\n                    remoteTypeName: __typename\n                  }\n                  ... on flexibleContent_leadText_BlockType {\n                    remoteTypeName: __typename\n                  }\n                  ... on flexibleContent_serviceDetail_BlockType {\n                    remoteTypeName: __typename\n                  }\n                  ... on rows_BlockType {\n                    remoteTypeName: __typename\n                  }\n                  ... on serviceDetailColumns_column_BlockType {\n                    remoteTypeName: __typename\n                  }\n                  ... on flexibleContent_subscriptionForm_BlockType {\n                    remoteTypeName: __typename\n                  }\n                  ... on flexibleContent_currentStatus_BlockType {\n                    remoteTypeName: __typename\n                  }\n                  ... on flexibleContent_informationGrid_BlockType {\n                    remoteTypeName: __typename\n                  }\n                  ... on flexibleContent_contactUs_BlockType {\n                    remoteTypeName: __typename\n                  }\n                  ... on options_BlockType {\n                    remoteTypeName: __typename\n                  }\n                  ... on flexibleContent_linkCards_BlockType {\n                    remoteTypeName: __typename\n                  }\n                  ... on serviceCategories_default_Entry {\n                    sourceId\n                    siteId\n                  }\n                  ... on pages_flexibleContent_Entry {\n                    sourceId\n                    siteId\n                  }\n                  ... on searchResults_searchResults_Entry {\n                    sourceId\n                    siteId\n                  }\n                  ... on pages_basic_Entry {\n                    sourceId\n                    siteId\n                  }\n                  ... on flexibleContentBasic_richText_BlockType {\n                    remoteTypeName: __typename\n                  }\n                  ... on flexibleContentBasic_image_BlockType {\n                    remoteTypeName: __typename\n                  }\n                  ... on servicesIndex_servicesIndex_Entry {\n                    sourceId\n                    siteId\n                  }\n                  ... on newsIndex_newsIndex_Entry {\n                    sourceId\n                    siteId\n                  }\n                  ... on newsArticle_default_Entry {\n                    sourceId\n                    siteId\n                  }\n                  ... on eventsIndex_eventsIndex_Entry {\n                    sourceId\n                    siteId\n                  }\n                  ... on eventsArticle_default_Entry {\n                    sourceId\n                    siteId\n                  }\n                  ... on serviceItems_default_Entry {\n                    sourceId\n                    siteId\n                  }\n                  ... on newsCategories_default_Entry {\n                    sourceId\n                    siteId\n                  }\n                  ... on images_Asset {\n                    remoteId: id\n                    siteId\n                  }\n                  ... on icons_Asset {\n                    remoteId: id\n                    siteId\n                  }\n                  ... on User {\n                    remoteId: id\n                    siteId\n                  }\n                  ... on General_GlobalSet {\n                    remoteId: id\n                    siteId\n                  }\n                  ... on seo_GlobalSet {\n                    remoteId: id\n                    siteId\n                  }\n                  ... on main_Node {\n                    remoteId: id\n                    siteId\n                  }\n                  ... on footerPrimary_Node {\n                    remoteId: id\n                    siteId\n                  }\n                  ... on footerSecondary_Node {\n                    remoteId: id\n                    siteId\n                  }\n                }\n                target\n                text\n                title\n                type\n                url\n              }\n            }\n            signaturePosition\n            backgroundColour\n            imagePosition\n          }\n        }\n      }\n    }\n    ... on cards_BlockType {\n      ... on cards_BlockType {\n        id\n        uid\n        title\n        slug\n        uri\n        enabled\n        archived\n        siteId\n        siteSettingsId\n        language\n        searchScore\n        trashed\n        status\n        dateCreated\n        dateUpdated\n        fieldId\n        ownerId\n        typeId\n        sortOrder\n        heading\n        body\n        headingLink {\n          remoteTypeName: __typename\n          ... on linkField_Link {\n            ariaLabel\n            customText\n            element {\n              remoteTypeName: __typename\n              ... on Element {\n                remoteTypeName: __typename\n              }\n              ... on home_home_Entry {\n                sourceId\n                siteId\n              }\n              ... on flexibleContent_heroCards_BlockType {\n                remoteTypeName: __typename\n              }\n              ... on cards_BlockType {\n                remoteTypeName: __typename\n              }\n              ... on flexibleContent_textAndImages_BlockType {\n                remoteTypeName: __typename\n              }\n              ... on flexibleContent_imageBanner_BlockType {\n                remoteTypeName: __typename\n              }\n              ... on flexibleContent_servicesCarousel_BlockType {\n                remoteTypeName: __typename\n              }\n              ... on flexibleContent_features_BlockType {\n                remoteTypeName: __typename\n              }\n              ... on flexibleContent_featuresPanel_BlockType {\n                remoteTypeName: __typename\n              }\n              ... on flexibleContent_featureCards_BlockType {\n                remoteTypeName: __typename\n              }\n              ... on flexibleContent_video_BlockType {\n                remoteTypeName: __typename\n              }\n              ... on flexibleContent_callToAction_BlockType {\n                remoteTypeName: __typename\n              }\n              ... on flexibleContent_careProfessionals_BlockType {\n                remoteTypeName: __typename\n              }\n              ... on flexibleContent_budgetGraph_BlockType {\n                remoteTypeName: __typename\n              }\n              ... on flexibleContent_reviewsCarousel_BlockType {\n                remoteTypeName: __typename\n              }\n              ... on reviews_BlockType {\n                remoteTypeName: __typename\n              }\n              ... on flexibleContent_textBlock_BlockType {\n                remoteTypeName: __typename\n              }\n              ... on flexibleContent_partnerCards_BlockType {\n                remoteTypeName: __typename\n              }\n              ... on partners_BlockType {\n                remoteTypeName: __typename\n              }\n              ... on flexibleContent_bCorp_BlockType {\n                remoteTypeName: __typename\n              }\n              ... on flexibleContent_pricing_BlockType {\n                remoteTypeName: __typename\n              }\n              ... on levelCard_BlockType {\n                remoteTypeName: __typename\n              }\n              ... on flexibleContent_contentColumns_BlockType {\n                remoteTypeName: __typename\n              }\n              ... on textColumns_BlockType {\n                remoteTypeName: __typename\n              }\n              ... on flexibleContent_accordionPanel_BlockType {\n                remoteTypeName: __typename\n              }\n              ... on items_BlockType {\n                remoteTypeName: __typename\n              }\n              ... on flexibleContent_leadHeading_BlockType {\n                remoteTypeName: __typename\n              }\n              ... on flexibleContent_leadText_BlockType {\n                remoteTypeName: __typename\n              }\n              ... on flexibleContent_serviceDetail_BlockType {\n                remoteTypeName: __typename\n              }\n              ... on rows_BlockType {\n                remoteTypeName: __typename\n              }\n              ... on serviceDetailColumns_column_BlockType {\n                remoteTypeName: __typename\n              }\n              ... on flexibleContent_subscriptionForm_BlockType {\n                remoteTypeName: __typename\n              }\n              ... on flexibleContent_currentStatus_BlockType {\n                remoteTypeName: __typename\n              }\n              ... on flexibleContent_informationGrid_BlockType {\n                remoteTypeName: __typename\n              }\n              ... on flexibleContent_contactUs_BlockType {\n                remoteTypeName: __typename\n              }\n              ... on options_BlockType {\n                remoteTypeName: __typename\n              }\n              ... on flexibleContent_linkCards_BlockType {\n                remoteTypeName: __typename\n              }\n              ... on serviceCategories_default_Entry {\n                sourceId\n                siteId\n              }\n              ... on pages_flexibleContent_Entry {\n                sourceId\n                siteId\n              }\n              ... on searchResults_searchResults_Entry {\n                sourceId\n                siteId\n              }\n              ... on pages_basic_Entry {\n                sourceId\n                siteId\n              }\n              ... on flexibleContentBasic_richText_BlockType {\n                remoteTypeName: __typename\n              }\n              ... on flexibleContentBasic_image_BlockType {\n                remoteTypeName: __typename\n              }\n              ... on servicesIndex_servicesIndex_Entry {\n                sourceId\n                siteId\n              }\n              ... on newsIndex_newsIndex_Entry {\n                sourceId\n                siteId\n              }\n              ... on newsArticle_default_Entry {\n                sourceId\n                siteId\n              }\n              ... on eventsIndex_eventsIndex_Entry {\n                sourceId\n                siteId\n              }\n              ... on eventsArticle_default_Entry {\n                sourceId\n                siteId\n              }\n              ... on serviceItems_default_Entry {\n                sourceId\n                siteId\n              }\n              ... on newsCategories_default_Entry {\n                sourceId\n                siteId\n              }\n              ... on images_Asset {\n                remoteId: id\n                siteId\n              }\n              ... on icons_Asset {\n                remoteId: id\n                siteId\n              }\n              ... on User {\n                remoteId: id\n                siteId\n              }\n              ... on General_GlobalSet {\n                remoteId: id\n                siteId\n              }\n              ... on seo_GlobalSet {\n                remoteId: id\n                siteId\n              }\n              ... on main_Node {\n                remoteId: id\n                siteId\n              }\n              ... on footerPrimary_Node {\n                remoteId: id\n                siteId\n              }\n              ... on footerSecondary_Node {\n                remoteId: id\n                siteId\n              }\n            }\n            target\n            text\n            title\n            type\n            url\n          }\n        }\n        image {\n          remoteTypeName: __typename\n          remoteId: id\n          siteId\n        }\n        signatureName\n        signatureText\n        signatureTextLink {\n          remoteTypeName: __typename\n          ... on linkField_Link {\n            ariaLabel\n            customText\n            element {\n              remoteTypeName: __typename\n              ... on Element {\n                remoteTypeName: __typename\n              }\n              ... on home_home_Entry {\n                sourceId\n                siteId\n              }\n              ... on flexibleContent_heroCards_BlockType {\n                remoteTypeName: __typename\n              }\n              ... on cards_BlockType {\n                remoteTypeName: __typename\n              }\n              ... on flexibleContent_textAndImages_BlockType {\n                remoteTypeName: __typename\n              }\n              ... on flexibleContent_imageBanner_BlockType {\n                remoteTypeName: __typename\n              }\n              ... on flexibleContent_servicesCarousel_BlockType {\n                remoteTypeName: __typename\n              }\n              ... on flexibleContent_features_BlockType {\n                remoteTypeName: __typename\n              }\n              ... on flexibleContent_featuresPanel_BlockType {\n                remoteTypeName: __typename\n              }\n              ... on flexibleContent_featureCards_BlockType {\n                remoteTypeName: __typename\n              }\n              ... on flexibleContent_video_BlockType {\n                remoteTypeName: __typename\n              }\n              ... on flexibleContent_callToAction_BlockType {\n                remoteTypeName: __typename\n              }\n              ... on flexibleContent_careProfessionals_BlockType {\n                remoteTypeName: __typename\n              }\n              ... on flexibleContent_budgetGraph_BlockType {\n                remoteTypeName: __typename\n              }\n              ... on flexibleContent_reviewsCarousel_BlockType {\n                remoteTypeName: __typename\n              }\n              ... on reviews_BlockType {\n                remoteTypeName: __typename\n              }\n              ... on flexibleContent_textBlock_BlockType {\n                remoteTypeName: __typename\n              }\n              ... on flexibleContent_partnerCards_BlockType {\n                remoteTypeName: __typename\n              }\n              ... on partners_BlockType {\n                remoteTypeName: __typename\n              }\n              ... on flexibleContent_bCorp_BlockType {\n                remoteTypeName: __typename\n              }\n              ... on flexibleContent_pricing_BlockType {\n                remoteTypeName: __typename\n              }\n              ... on levelCard_BlockType {\n                remoteTypeName: __typename\n              }\n              ... on flexibleContent_contentColumns_BlockType {\n                remoteTypeName: __typename\n              }\n              ... on textColumns_BlockType {\n                remoteTypeName: __typename\n              }\n              ... on flexibleContent_accordionPanel_BlockType {\n                remoteTypeName: __typename\n              }\n              ... on items_BlockType {\n                remoteTypeName: __typename\n              }\n              ... on flexibleContent_leadHeading_BlockType {\n                remoteTypeName: __typename\n              }\n              ... on flexibleContent_leadText_BlockType {\n                remoteTypeName: __typename\n              }\n              ... on flexibleContent_serviceDetail_BlockType {\n                remoteTypeName: __typename\n              }\n              ... on rows_BlockType {\n                remoteTypeName: __typename\n              }\n              ... on serviceDetailColumns_column_BlockType {\n                remoteTypeName: __typename\n              }\n              ... on flexibleContent_subscriptionForm_BlockType {\n                remoteTypeName: __typename\n              }\n              ... on flexibleContent_currentStatus_BlockType {\n                remoteTypeName: __typename\n              }\n              ... on flexibleContent_informationGrid_BlockType {\n                remoteTypeName: __typename\n              }\n              ... on flexibleContent_contactUs_BlockType {\n                remoteTypeName: __typename\n              }\n              ... on options_BlockType {\n                remoteTypeName: __typename\n              }\n              ... on flexibleContent_linkCards_BlockType {\n                remoteTypeName: __typename\n              }\n              ... on serviceCategories_default_Entry {\n                sourceId\n                siteId\n              }\n              ... on pages_flexibleContent_Entry {\n                sourceId\n                siteId\n              }\n              ... on searchResults_searchResults_Entry {\n                sourceId\n                siteId\n              }\n              ... on pages_basic_Entry {\n                sourceId\n                siteId\n              }\n              ... on flexibleContentBasic_richText_BlockType {\n                remoteTypeName: __typename\n              }\n              ... on flexibleContentBasic_image_BlockType {\n                remoteTypeName: __typename\n              }\n              ... on servicesIndex_servicesIndex_Entry {\n                sourceId\n                siteId\n              }\n              ... on newsIndex_newsIndex_Entry {\n                sourceId\n                siteId\n              }\n              ... on newsArticle_default_Entry {\n                sourceId\n                siteId\n              }\n              ... on eventsIndex_eventsIndex_Entry {\n                sourceId\n                siteId\n              }\n              ... on eventsArticle_default_Entry {\n                sourceId\n                siteId\n              }\n              ... on serviceItems_default_Entry {\n                sourceId\n                siteId\n              }\n              ... on newsCategories_default_Entry {\n                sourceId\n                siteId\n              }\n              ... on images_Asset {\n                remoteId: id\n                siteId\n              }\n              ... on icons_Asset {\n                remoteId: id\n                siteId\n              }\n              ... on User {\n                remoteId: id\n                siteId\n              }\n              ... on General_GlobalSet {\n                remoteId: id\n                siteId\n              }\n              ... on seo_GlobalSet {\n                remoteId: id\n                siteId\n              }\n              ... on main_Node {\n                remoteId: id\n                siteId\n              }\n              ... on footerPrimary_Node {\n                remoteId: id\n                siteId\n              }\n              ... on footerSecondary_Node {\n                remoteId: id\n                siteId\n              }\n            }\n            target\n            text\n            title\n            type\n            url\n          }\n        }\n        signaturePosition\n        backgroundColour\n        imagePosition\n      }\n    }\n    ... on flexibleContent_textAndImages_BlockType {\n      ... on flexibleContent_textAndImages_BlockType {\n        id\n        uid\n        title\n        slug\n        uri\n        enabled\n        archived\n        siteId\n        siteSettingsId\n        language\n        searchScore\n        trashed\n        status\n        dateCreated\n        dateUpdated\n        fieldId\n        ownerId\n        typeId\n        typeHandle\n        sortOrder\n        images {\n          remoteTypeName: __typename\n          remoteId: id\n          siteId\n        }\n        imageAlignment\n        imageOffset\n        imageWidth\n        body\n        centreText\n        button {\n          remoteTypeName: __typename\n          ... on linkField_Link {\n            ariaLabel\n            customText\n            element {\n              remoteTypeName: __typename\n              ... on Element {\n                remoteTypeName: __typename\n              }\n              ... on home_home_Entry {\n                sourceId\n                siteId\n              }\n              ... on flexibleContent_heroCards_BlockType {\n                remoteTypeName: __typename\n              }\n              ... on cards_BlockType {\n                remoteTypeName: __typename\n              }\n              ... on flexibleContent_textAndImages_BlockType {\n                remoteTypeName: __typename\n              }\n              ... on flexibleContent_imageBanner_BlockType {\n                remoteTypeName: __typename\n              }\n              ... on flexibleContent_servicesCarousel_BlockType {\n                remoteTypeName: __typename\n              }\n              ... on flexibleContent_features_BlockType {\n                remoteTypeName: __typename\n              }\n              ... on flexibleContent_featuresPanel_BlockType {\n                remoteTypeName: __typename\n              }\n              ... on flexibleContent_featureCards_BlockType {\n                remoteTypeName: __typename\n              }\n              ... on flexibleContent_video_BlockType {\n                remoteTypeName: __typename\n              }\n              ... on flexibleContent_callToAction_BlockType {\n                remoteTypeName: __typename\n              }\n              ... on flexibleContent_careProfessionals_BlockType {\n                remoteTypeName: __typename\n              }\n              ... on flexibleContent_budgetGraph_BlockType {\n                remoteTypeName: __typename\n              }\n              ... on flexibleContent_reviewsCarousel_BlockType {\n                remoteTypeName: __typename\n              }\n              ... on reviews_BlockType {\n                remoteTypeName: __typename\n              }\n              ... on flexibleContent_textBlock_BlockType {\n                remoteTypeName: __typename\n              }\n              ... on flexibleContent_partnerCards_BlockType {\n                remoteTypeName: __typename\n              }\n              ... on partners_BlockType {\n                remoteTypeName: __typename\n              }\n              ... on flexibleContent_bCorp_BlockType {\n                remoteTypeName: __typename\n              }\n              ... on flexibleContent_pricing_BlockType {\n                remoteTypeName: __typename\n              }\n              ... on levelCard_BlockType {\n                remoteTypeName: __typename\n              }\n              ... on flexibleContent_contentColumns_BlockType {\n                remoteTypeName: __typename\n              }\n              ... on textColumns_BlockType {\n                remoteTypeName: __typename\n              }\n              ... on flexibleContent_accordionPanel_BlockType {\n                remoteTypeName: __typename\n              }\n              ... on items_BlockType {\n                remoteTypeName: __typename\n              }\n              ... on flexibleContent_leadHeading_BlockType {\n                remoteTypeName: __typename\n              }\n              ... on flexibleContent_leadText_BlockType {\n                remoteTypeName: __typename\n              }\n              ... on flexibleContent_serviceDetail_BlockType {\n                remoteTypeName: __typename\n              }\n              ... on rows_BlockType {\n                remoteTypeName: __typename\n              }\n              ... on serviceDetailColumns_column_BlockType {\n                remoteTypeName: __typename\n              }\n              ... on flexibleContent_subscriptionForm_BlockType {\n                remoteTypeName: __typename\n              }\n              ... on flexibleContent_currentStatus_BlockType {\n                remoteTypeName: __typename\n              }\n              ... on flexibleContent_informationGrid_BlockType {\n                remoteTypeName: __typename\n              }\n              ... on flexibleContent_contactUs_BlockType {\n                remoteTypeName: __typename\n              }\n              ... on options_BlockType {\n                remoteTypeName: __typename\n              }\n              ... on flexibleContent_linkCards_BlockType {\n                remoteTypeName: __typename\n              }\n              ... on serviceCategories_default_Entry {\n                sourceId\n                siteId\n              }\n              ... on pages_flexibleContent_Entry {\n                sourceId\n                siteId\n              }\n              ... on searchResults_searchResults_Entry {\n                sourceId\n                siteId\n              }\n              ... on pages_basic_Entry {\n                sourceId\n                siteId\n              }\n              ... on flexibleContentBasic_richText_BlockType {\n                remoteTypeName: __typename\n              }\n              ... on flexibleContentBasic_image_BlockType {\n                remoteTypeName: __typename\n              }\n              ... on servicesIndex_servicesIndex_Entry {\n                sourceId\n                siteId\n              }\n              ... on newsIndex_newsIndex_Entry {\n                sourceId\n                siteId\n              }\n              ... on newsArticle_default_Entry {\n                sourceId\n                siteId\n              }\n              ... on eventsIndex_eventsIndex_Entry {\n                sourceId\n                siteId\n              }\n              ... on eventsArticle_default_Entry {\n                sourceId\n                siteId\n              }\n              ... on serviceItems_default_Entry {\n                sourceId\n                siteId\n              }\n              ... on newsCategories_default_Entry {\n                sourceId\n                siteId\n              }\n              ... on images_Asset {\n                remoteId: id\n                siteId\n              }\n              ... on icons_Asset {\n                remoteId: id\n                siteId\n              }\n              ... on User {\n                remoteId: id\n                siteId\n              }\n              ... on General_GlobalSet {\n                remoteId: id\n                siteId\n              }\n              ... on seo_GlobalSet {\n                remoteId: id\n                siteId\n              }\n              ... on main_Node {\n                remoteId: id\n                siteId\n              }\n              ... on footerPrimary_Node {\n                remoteId: id\n                siteId\n              }\n              ... on footerSecondary_Node {\n                remoteId: id\n                siteId\n              }\n            }\n            target\n            text\n            title\n            type\n            url\n          }\n        }\n        signatureName\n        signatureText\n      }\n    }\n    ... on flexibleContent_imageBanner_BlockType {\n      ... on flexibleContent_imageBanner_BlockType {\n        id\n        uid\n        title\n        slug\n        uri\n        enabled\n        archived\n        siteId\n        siteSettingsId\n        language\n        searchScore\n        trashed\n        status\n        dateCreated\n        dateUpdated\n        fieldId\n        ownerId\n        typeId\n        typeHandle\n        sortOrder\n        image {\n          remoteTypeName: __typename\n          remoteId: id\n          siteId\n        }\n        imageMobile {\n          remoteTypeName: __typename\n          remoteId: id\n          siteId\n        }\n        imageSize\n        signatureName\n        signatureText\n      }\n    }\n    ... on flexibleContent_servicesCarousel_BlockType {\n      ... on flexibleContent_servicesCarousel_BlockType {\n        id\n        uid\n        title\n        slug\n        uri\n        enabled\n        archived\n        siteId\n        siteSettingsId\n        language\n        searchScore\n        trashed\n        status\n        dateCreated\n        dateUpdated\n        fieldId\n        ownerId\n        typeId\n        typeHandle\n        sortOrder\n        heading\n        services {\n          remoteTypeName: __typename\n          sourceId\n          siteId\n        }\n      }\n    }\n    ... on flexibleContent_features_BlockType {\n      ... on flexibleContent_features_BlockType {\n        id\n        uid\n        title\n        slug\n        uri\n        enabled\n        archived\n        siteId\n        siteSettingsId\n        language\n        searchScore\n        trashed\n        status\n        dateCreated\n        dateUpdated\n        fieldId\n        ownerId\n        typeId\n        typeHandle\n        sortOrder\n        heading\n        subheading\n        items {\n          remoteTypeName: __typename\n          ... on items_TableRow {\n            col1\n            heading\n            col2\n            text\n          }\n        }\n        button {\n          remoteTypeName: __typename\n          ... on linkField_Link {\n            ariaLabel\n            customText\n            element {\n              remoteTypeName: __typename\n              ... on Element {\n                remoteTypeName: __typename\n              }\n              ... on home_home_Entry {\n                sourceId\n                siteId\n              }\n              ... on flexibleContent_heroCards_BlockType {\n                remoteTypeName: __typename\n              }\n              ... on cards_BlockType {\n                remoteTypeName: __typename\n              }\n              ... on flexibleContent_textAndImages_BlockType {\n                remoteTypeName: __typename\n              }\n              ... on flexibleContent_imageBanner_BlockType {\n                remoteTypeName: __typename\n              }\n              ... on flexibleContent_servicesCarousel_BlockType {\n                remoteTypeName: __typename\n              }\n              ... on flexibleContent_features_BlockType {\n                remoteTypeName: __typename\n              }\n              ... on flexibleContent_featuresPanel_BlockType {\n                remoteTypeName: __typename\n              }\n              ... on flexibleContent_featureCards_BlockType {\n                remoteTypeName: __typename\n              }\n              ... on flexibleContent_video_BlockType {\n                remoteTypeName: __typename\n              }\n              ... on flexibleContent_callToAction_BlockType {\n                remoteTypeName: __typename\n              }\n              ... on flexibleContent_careProfessionals_BlockType {\n                remoteTypeName: __typename\n              }\n              ... on flexibleContent_budgetGraph_BlockType {\n                remoteTypeName: __typename\n              }\n              ... on flexibleContent_reviewsCarousel_BlockType {\n                remoteTypeName: __typename\n              }\n              ... on reviews_BlockType {\n                remoteTypeName: __typename\n              }\n              ... on flexibleContent_textBlock_BlockType {\n                remoteTypeName: __typename\n              }\n              ... on flexibleContent_partnerCards_BlockType {\n                remoteTypeName: __typename\n              }\n              ... on partners_BlockType {\n                remoteTypeName: __typename\n              }\n              ... on flexibleContent_bCorp_BlockType {\n                remoteTypeName: __typename\n              }\n              ... on flexibleContent_pricing_BlockType {\n                remoteTypeName: __typename\n              }\n              ... on levelCard_BlockType {\n                remoteTypeName: __typename\n              }\n              ... on flexibleContent_contentColumns_BlockType {\n                remoteTypeName: __typename\n              }\n              ... on textColumns_BlockType {\n                remoteTypeName: __typename\n              }\n              ... on flexibleContent_accordionPanel_BlockType {\n                remoteTypeName: __typename\n              }\n              ... on items_BlockType {\n                remoteTypeName: __typename\n              }\n              ... on flexibleContent_leadHeading_BlockType {\n                remoteTypeName: __typename\n              }\n              ... on flexibleContent_leadText_BlockType {\n                remoteTypeName: __typename\n              }\n              ... on flexibleContent_serviceDetail_BlockType {\n                remoteTypeName: __typename\n              }\n              ... on rows_BlockType {\n                remoteTypeName: __typename\n              }\n              ... on serviceDetailColumns_column_BlockType {\n                remoteTypeName: __typename\n              }\n              ... on flexibleContent_subscriptionForm_BlockType {\n                remoteTypeName: __typename\n              }\n              ... on flexibleContent_currentStatus_BlockType {\n                remoteTypeName: __typename\n              }\n              ... on flexibleContent_informationGrid_BlockType {\n                remoteTypeName: __typename\n              }\n              ... on flexibleContent_contactUs_BlockType {\n                remoteTypeName: __typename\n              }\n              ... on options_BlockType {\n                remoteTypeName: __typename\n              }\n              ... on flexibleContent_linkCards_BlockType {\n                remoteTypeName: __typename\n              }\n              ... on serviceCategories_default_Entry {\n                sourceId\n                siteId\n              }\n              ... on pages_flexibleContent_Entry {\n                sourceId\n                siteId\n              }\n              ... on searchResults_searchResults_Entry {\n                sourceId\n                siteId\n              }\n              ... on pages_basic_Entry {\n                sourceId\n                siteId\n              }\n              ... on flexibleContentBasic_richText_BlockType {\n                remoteTypeName: __typename\n              }\n              ... on flexibleContentBasic_image_BlockType {\n                remoteTypeName: __typename\n              }\n              ... on servicesIndex_servicesIndex_Entry {\n                sourceId\n                siteId\n              }\n              ... on newsIndex_newsIndex_Entry {\n                sourceId\n                siteId\n              }\n              ... on newsArticle_default_Entry {\n                sourceId\n                siteId\n              }\n              ... on eventsIndex_eventsIndex_Entry {\n                sourceId\n                siteId\n              }\n              ... on eventsArticle_default_Entry {\n                sourceId\n                siteId\n              }\n              ... on serviceItems_default_Entry {\n                sourceId\n                siteId\n              }\n              ... on newsCategories_default_Entry {\n                sourceId\n                siteId\n              }\n              ... on images_Asset {\n                remoteId: id\n                siteId\n              }\n              ... on icons_Asset {\n                remoteId: id\n                siteId\n              }\n              ... on User {\n                remoteId: id\n                siteId\n              }\n              ... on General_GlobalSet {\n                remoteId: id\n                siteId\n              }\n              ... on seo_GlobalSet {\n                remoteId: id\n                siteId\n              }\n              ... on main_Node {\n                remoteId: id\n                siteId\n              }\n              ... on footerPrimary_Node {\n                remoteId: id\n                siteId\n              }\n              ... on footerSecondary_Node {\n                remoteId: id\n                siteId\n              }\n            }\n            target\n            text\n            title\n            type\n            url\n          }\n        }\n        style\n        buttonSize\n      }\n    }\n    ... on flexibleContent_featuresPanel_BlockType {\n      ... on flexibleContent_featuresPanel_BlockType {\n        id\n        uid\n        title\n        slug\n        uri\n        enabled\n        archived\n        siteId\n        siteSettingsId\n        language\n        searchScore\n        trashed\n        status\n        dateCreated\n        dateUpdated\n        fieldId\n        ownerId\n        typeId\n        typeHandle\n        sortOrder\n        heading\n        backgroundColour\n        items {\n          remoteTypeName: __typename\n          ... on items_TableRow {\n            col1\n            heading\n            col2\n            text\n          }\n        }\n        image {\n          remoteTypeName: __typename\n          remoteId: id\n          siteId\n        }\n      }\n    }\n    ... on flexibleContent_featureCards_BlockType {\n      ... on flexibleContent_featureCards_BlockType {\n        id\n        uid\n        title\n        slug\n        uri\n        enabled\n        archived\n        siteId\n        siteSettingsId\n        language\n        searchScore\n        trashed\n        status\n        dateCreated\n        dateUpdated\n        fieldId\n        ownerId\n        typeId\n        typeHandle\n        sortOrder\n        heading\n        text\n        cards {\n          remoteTypeName: __typename\n          ... on cards_TableRow {\n            col1\n            heading\n            col2\n            text\n          }\n        }\n      }\n    }\n    ... on flexibleContent_video_BlockType {\n      ... on flexibleContent_video_BlockType {\n        id\n        uid\n        title\n        slug\n        uri\n        enabled\n        archived\n        siteId\n        siteSettingsId\n        language\n        searchScore\n        trashed\n        status\n        dateCreated\n        dateUpdated\n        fieldId\n        ownerId\n        typeId\n        typeHandle\n        sortOrder\n        heading\n        subheading\n        videoId\n        posterImage {\n          remoteTypeName: __typename\n          remoteId: id\n          siteId\n        }\n        backgroundGradient\n      }\n    }\n    ... on flexibleContent_callToAction_BlockType {\n      ... on flexibleContent_callToAction_BlockType {\n        id\n        uid\n        title\n        slug\n        uri\n        enabled\n        archived\n        siteId\n        siteSettingsId\n        language\n        searchScore\n        trashed\n        status\n        dateCreated\n        dateUpdated\n        fieldId\n        ownerId\n        typeId\n        typeHandle\n        sortOrder\n        text\n        button {\n          remoteTypeName: __typename\n          ... on linkField_Link {\n            ariaLabel\n            customText\n            element {\n              remoteTypeName: __typename\n              ... on Element {\n                remoteTypeName: __typename\n              }\n              ... on home_home_Entry {\n                sourceId\n                siteId\n              }\n              ... on flexibleContent_heroCards_BlockType {\n                remoteTypeName: __typename\n              }\n              ... on cards_BlockType {\n                remoteTypeName: __typename\n              }\n              ... on flexibleContent_textAndImages_BlockType {\n                remoteTypeName: __typename\n              }\n              ... on flexibleContent_imageBanner_BlockType {\n                remoteTypeName: __typename\n              }\n              ... on flexibleContent_servicesCarousel_BlockType {\n                remoteTypeName: __typename\n              }\n              ... on flexibleContent_features_BlockType {\n                remoteTypeName: __typename\n              }\n              ... on flexibleContent_featuresPanel_BlockType {\n                remoteTypeName: __typename\n              }\n              ... on flexibleContent_featureCards_BlockType {\n                remoteTypeName: __typename\n              }\n              ... on flexibleContent_video_BlockType {\n                remoteTypeName: __typename\n              }\n              ... on flexibleContent_callToAction_BlockType {\n                remoteTypeName: __typename\n              }\n              ... on flexibleContent_careProfessionals_BlockType {\n                remoteTypeName: __typename\n              }\n              ... on flexibleContent_budgetGraph_BlockType {\n                remoteTypeName: __typename\n              }\n              ... on flexibleContent_reviewsCarousel_BlockType {\n                remoteTypeName: __typename\n              }\n              ... on reviews_BlockType {\n                remoteTypeName: __typename\n              }\n              ... on flexibleContent_textBlock_BlockType {\n                remoteTypeName: __typename\n              }\n              ... on flexibleContent_partnerCards_BlockType {\n                remoteTypeName: __typename\n              }\n              ... on partners_BlockType {\n                remoteTypeName: __typename\n              }\n              ... on flexibleContent_bCorp_BlockType {\n                remoteTypeName: __typename\n              }\n              ... on flexibleContent_pricing_BlockType {\n                remoteTypeName: __typename\n              }\n              ... on levelCard_BlockType {\n                remoteTypeName: __typename\n              }\n              ... on flexibleContent_contentColumns_BlockType {\n                remoteTypeName: __typename\n              }\n              ... on textColumns_BlockType {\n                remoteTypeName: __typename\n              }\n              ... on flexibleContent_accordionPanel_BlockType {\n                remoteTypeName: __typename\n              }\n              ... on items_BlockType {\n                remoteTypeName: __typename\n              }\n              ... on flexibleContent_leadHeading_BlockType {\n                remoteTypeName: __typename\n              }\n              ... on flexibleContent_leadText_BlockType {\n                remoteTypeName: __typename\n              }\n              ... on flexibleContent_serviceDetail_BlockType {\n                remoteTypeName: __typename\n              }\n              ... on rows_BlockType {\n                remoteTypeName: __typename\n              }\n              ... on serviceDetailColumns_column_BlockType {\n                remoteTypeName: __typename\n              }\n              ... on flexibleContent_subscriptionForm_BlockType {\n                remoteTypeName: __typename\n              }\n              ... on flexibleContent_currentStatus_BlockType {\n                remoteTypeName: __typename\n              }\n              ... on flexibleContent_informationGrid_BlockType {\n                remoteTypeName: __typename\n              }\n              ... on flexibleContent_contactUs_BlockType {\n                remoteTypeName: __typename\n              }\n              ... on options_BlockType {\n                remoteTypeName: __typename\n              }\n              ... on flexibleContent_linkCards_BlockType {\n                remoteTypeName: __typename\n              }\n              ... on serviceCategories_default_Entry {\n                sourceId\n                siteId\n              }\n              ... on pages_flexibleContent_Entry {\n                sourceId\n                siteId\n              }\n              ... on searchResults_searchResults_Entry {\n                sourceId\n                siteId\n              }\n              ... on pages_basic_Entry {\n                sourceId\n                siteId\n              }\n              ... on flexibleContentBasic_richText_BlockType {\n                remoteTypeName: __typename\n              }\n              ... on flexibleContentBasic_image_BlockType {\n                remoteTypeName: __typename\n              }\n              ... on servicesIndex_servicesIndex_Entry {\n                sourceId\n                siteId\n              }\n              ... on newsIndex_newsIndex_Entry {\n                sourceId\n                siteId\n              }\n              ... on newsArticle_default_Entry {\n                sourceId\n                siteId\n              }\n              ... on eventsIndex_eventsIndex_Entry {\n                sourceId\n                siteId\n              }\n              ... on eventsArticle_default_Entry {\n                sourceId\n                siteId\n              }\n              ... on serviceItems_default_Entry {\n                sourceId\n                siteId\n              }\n              ... on newsCategories_default_Entry {\n                sourceId\n                siteId\n              }\n              ... on images_Asset {\n                remoteId: id\n                siteId\n              }\n              ... on icons_Asset {\n                remoteId: id\n                siteId\n              }\n              ... on User {\n                remoteId: id\n                siteId\n              }\n              ... on General_GlobalSet {\n                remoteId: id\n                siteId\n              }\n              ... on seo_GlobalSet {\n                remoteId: id\n                siteId\n              }\n              ... on main_Node {\n                remoteId: id\n                siteId\n              }\n              ... on footerPrimary_Node {\n                remoteId: id\n                siteId\n              }\n              ... on footerSecondary_Node {\n                remoteId: id\n                siteId\n              }\n            }\n            target\n            text\n            title\n            type\n            url\n          }\n        }\n        textColour\n        backgroundColour\n        unityMark\n      }\n    }\n    ... on flexibleContent_careProfessionals_BlockType {\n      ... on flexibleContent_careProfessionals_BlockType {\n        id\n        uid\n        title\n        slug\n        uri\n        enabled\n        archived\n        siteId\n        siteSettingsId\n        language\n        searchScore\n        trashed\n        status\n        dateCreated\n        dateUpdated\n        fieldId\n        ownerId\n        typeId\n        typeHandle\n        sortOrder\n        heading\n        hoursSinceCreationDisplay\n        backgroundColour\n        unityMark\n      }\n    }\n    ... on flexibleContent_budgetGraph_BlockType {\n      ... on flexibleContent_budgetGraph_BlockType {\n        id\n        uid\n        title\n        slug\n        uri\n        enabled\n        archived\n        siteId\n        siteSettingsId\n        language\n        searchScore\n        trashed\n        status\n        dateCreated\n        dateUpdated\n        fieldId\n        ownerId\n        typeId\n        typeHandle\n        sortOrder\n        heading\n        subheading\n        unityMarkHeading\n        industryRate\n        industryRateCaption\n        frankieRateHeading\n        frankieRate\n        frankieRateCaption\n        frankieRateSavings\n        backgroundGradient\n      }\n    }\n    ... on flexibleContent_reviewsCarousel_BlockType {\n      ... on flexibleContent_reviewsCarousel_BlockType {\n        id\n        uid\n        title\n        slug\n        uri\n        enabled\n        archived\n        siteId\n        siteSettingsId\n        language\n        searchScore\n        trashed\n        status\n        dateCreated\n        dateUpdated\n        fieldId\n        ownerId\n        typeId\n        typeHandle\n        sortOrder\n        heading\n        reviews {\n          remoteTypeName: __typename\n          ... on reviews_BlockType {\n            id\n            uid\n            title\n            slug\n            uri\n            enabled\n            archived\n            siteId\n            siteSettingsId\n            language\n            searchScore\n            trashed\n            status\n            dateCreated\n            dateUpdated\n            fieldId\n            ownerId\n            typeId\n            sortOrder\n            heading\n            subheading\n            text\n          }\n        }\n      }\n    }\n    ... on reviews_BlockType {\n      ... on reviews_BlockType {\n        id\n        uid\n        title\n        slug\n        uri\n        enabled\n        archived\n        siteId\n        siteSettingsId\n        language\n        searchScore\n        trashed\n        status\n        dateCreated\n        dateUpdated\n        fieldId\n        ownerId\n        typeId\n        sortOrder\n        heading\n        subheading\n        text\n      }\n    }\n    ... on flexibleContent_textBlock_BlockType {\n      ... on flexibleContent_textBlock_BlockType {\n        id\n        uid\n        title\n        slug\n        uri\n        enabled\n        archived\n        siteId\n        siteSettingsId\n        language\n        searchScore\n        trashed\n        status\n        dateCreated\n        dateUpdated\n        fieldId\n        ownerId\n        typeId\n        typeHandle\n        sortOrder\n        header\n        headerTextColour\n        text\n        textColour\n        backgroundColour\n      }\n    }\n    ... on flexibleContent_partnerCards_BlockType {\n      ... on flexibleContent_partnerCards_BlockType {\n        id\n        uid\n        title\n        slug\n        uri\n        enabled\n        archived\n        siteId\n        siteSettingsId\n        language\n        searchScore\n        trashed\n        status\n        dateCreated\n        dateUpdated\n        fieldId\n        ownerId\n        typeId\n        typeHandle\n        sortOrder\n        heading\n        partners {\n          remoteTypeName: __typename\n          ... on partners_BlockType {\n            id\n            uid\n            title\n            slug\n            uri\n            enabled\n            archived\n            siteId\n            siteSettingsId\n            language\n            searchScore\n            trashed\n            status\n            dateCreated\n            dateUpdated\n            fieldId\n            ownerId\n            typeId\n            sortOrder\n            logo {\n              remoteTypeName: __typename\n              remoteId: id\n              siteId\n            }\n            body\n            websiteLink\n          }\n        }\n      }\n    }\n    ... on partners_BlockType {\n      ... on partners_BlockType {\n        id\n        uid\n        title\n        slug\n        uri\n        enabled\n        archived\n        siteId\n        siteSettingsId\n        language\n        searchScore\n        trashed\n        status\n        dateCreated\n        dateUpdated\n        fieldId\n        ownerId\n        typeId\n        sortOrder\n        logo {\n          remoteTypeName: __typename\n          remoteId: id\n          siteId\n        }\n        body\n        websiteLink\n      }\n    }\n    ... on flexibleContent_bCorp_BlockType {\n      ... on flexibleContent_bCorp_BlockType {\n        id\n        uid\n        title\n        slug\n        uri\n        enabled\n        archived\n        siteId\n        siteSettingsId\n        language\n        searchScore\n        trashed\n        status\n        dateCreated\n        dateUpdated\n        fieldId\n        ownerId\n        typeId\n        typeHandle\n        sortOrder\n        heading\n        lead\n        body\n      }\n    }\n    ... on flexibleContent_pricing_BlockType {\n      ... on flexibleContent_pricing_BlockType {\n        id\n        uid\n        title\n        slug\n        uri\n        enabled\n        archived\n        siteId\n        siteSettingsId\n        language\n        searchScore\n        trashed\n        status\n        dateCreated\n        dateUpdated\n        fieldId\n        ownerId\n        typeId\n        typeHandle\n        sortOrder\n        heading\n        lead\n        levelCard {\n          remoteTypeName: __typename\n          ... on levelCard_BlockType {\n            id\n            uid\n            title\n            slug\n            uri\n            enabled\n            archived\n            siteId\n            siteSettingsId\n            language\n            searchScore\n            trashed\n            status\n            dateCreated\n            dateUpdated\n            fieldId\n            ownerId\n            typeId\n            sortOrder\n            heading\n            services {\n              remoteTypeName: __typename\n              sourceId\n              siteId\n            }\n            packageValue\n            hoursWeek\n            finePrint\n          }\n        }\n        packageValueFinePrint\n        image {\n          remoteTypeName: __typename\n          remoteId: id\n          siteId\n        }\n      }\n    }\n    ... on levelCard_BlockType {\n      ... on levelCard_BlockType {\n        id\n        uid\n        title\n        slug\n        uri\n        enabled\n        archived\n        siteId\n        siteSettingsId\n        language\n        searchScore\n        trashed\n        status\n        dateCreated\n        dateUpdated\n        fieldId\n        ownerId\n        typeId\n        sortOrder\n        heading\n        services {\n          remoteTypeName: __typename\n          sourceId\n          siteId\n        }\n        packageValue\n        hoursWeek\n        finePrint\n      }\n    }\n    ... on flexibleContent_contentColumns_BlockType {\n      ... on flexibleContent_contentColumns_BlockType {\n        id\n        uid\n        title\n        slug\n        uri\n        enabled\n        archived\n        siteId\n        siteSettingsId\n        language\n        searchScore\n        trashed\n        status\n        dateCreated\n        dateUpdated\n        fieldId\n        ownerId\n        typeId\n        typeHandle\n        sortOrder\n        textColumns {\n          remoteTypeName: __typename\n          ... on textColumns_BlockType {\n            id\n            uid\n            title\n            slug\n            uri\n            enabled\n            archived\n            siteId\n            siteSettingsId\n            language\n            searchScore\n            trashed\n            status\n            dateCreated\n            dateUpdated\n            fieldId\n            ownerId\n            typeId\n            sortOrder\n            body\n          }\n        }\n      }\n    }\n    ... on textColumns_BlockType {\n      ... on textColumns_BlockType {\n        id\n        uid\n        title\n        slug\n        uri\n        enabled\n        archived\n        siteId\n        siteSettingsId\n        language\n        searchScore\n        trashed\n        status\n        dateCreated\n        dateUpdated\n        fieldId\n        ownerId\n        typeId\n        sortOrder\n        body\n      }\n    }\n    ... on flexibleContent_accordionPanel_BlockType {\n      ... on flexibleContent_accordionPanel_BlockType {\n        id\n        uid\n        title\n        slug\n        uri\n        enabled\n        archived\n        siteId\n        siteSettingsId\n        language\n        searchScore\n        trashed\n        status\n        dateCreated\n        dateUpdated\n        fieldId\n        ownerId\n        typeId\n        typeHandle\n        sortOrder\n        heading\n        items {\n          remoteTypeName: __typename\n          ... on items_BlockType {\n            id\n            uid\n            title\n            slug\n            uri\n            enabled\n            archived\n            siteId\n            siteSettingsId\n            language\n            searchScore\n            trashed\n            status\n            dateCreated\n            dateUpdated\n            fieldId\n            ownerId\n            typeId\n            sortOrder\n            heading\n            text\n            icon {\n              remoteTypeName: __typename\n              remoteId: id\n              siteId\n            }\n          }\n        }\n        image {\n          remoteTypeName: __typename\n          remoteId: id\n          siteId\n        }\n        backgroundColour\n        signatureName\n        signatureText\n      }\n    }\n    ... on items_BlockType {\n      ... on items_BlockType {\n        id\n        uid\n        title\n        slug\n        uri\n        enabled\n        archived\n        siteId\n        siteSettingsId\n        language\n        searchScore\n        trashed\n        status\n        dateCreated\n        dateUpdated\n        fieldId\n        ownerId\n        typeId\n        sortOrder\n        heading\n        text\n        icon {\n          remoteTypeName: __typename\n          remoteId: id\n          siteId\n        }\n      }\n    }\n    ... on flexibleContent_leadHeading_BlockType {\n      ... on flexibleContent_leadHeading_BlockType {\n        id\n        uid\n        title\n        slug\n        uri\n        enabled\n        archived\n        siteId\n        siteSettingsId\n        language\n        searchScore\n        trashed\n        status\n        dateCreated\n        dateUpdated\n        fieldId\n        ownerId\n        typeId\n        typeHandle\n        sortOrder\n        heading\n        headingColour\n        text\n      }\n    }\n    ... on flexibleContent_leadText_BlockType {\n      ... on flexibleContent_leadText_BlockType {\n        id\n        uid\n        title\n        slug\n        uri\n        enabled\n        archived\n        siteId\n        siteSettingsId\n        language\n        searchScore\n        trashed\n        status\n        dateCreated\n        dateUpdated\n        fieldId\n        ownerId\n        typeId\n        typeHandle\n        sortOrder\n        heading\n        headingColour\n      }\n    }\n    ... on flexibleContent_serviceDetail_BlockType {\n      ... on flexibleContent_serviceDetail_BlockType {\n        id\n        uid\n        title\n        slug\n        uri\n        enabled\n        archived\n        siteId\n        siteSettingsId\n        language\n        searchScore\n        trashed\n        status\n        dateCreated\n        dateUpdated\n        fieldId\n        ownerId\n        typeId\n        typeHandle\n        sortOrder\n        rows {\n          remoteTypeName: __typename\n          ... on rows_BlockType {\n            id\n            uid\n            title\n            slug\n            uri\n            enabled\n            archived\n            siteId\n            siteSettingsId\n            language\n            searchScore\n            trashed\n            status\n            dateCreated\n            dateUpdated\n            fieldId\n            ownerId\n            typeId\n            sortOrder\n            heading\n            unityMark\n            serviceDetailColumns {\n              remoteTypeName: __typename\n              ... on serviceDetailColumns_column_BlockType {\n                id\n                uid\n                title\n                slug\n                uri\n                enabled\n                archived\n                siteId\n                siteSettingsId\n                language\n                searchScore\n                trashed\n                status\n                dateCreated\n                dateUpdated\n                fieldId\n                ownerId\n                typeId\n                typeHandle\n                sortOrder\n                service {\n                  remoteTypeName: __typename\n                  sourceId\n                  siteId\n                }\n                heading\n                text\n              }\n            }\n          }\n        }\n        image {\n          remoteTypeName: __typename\n          remoteId: id\n          siteId\n        }\n        backgroundColour\n      }\n    }\n    ... on rows_BlockType {\n      ... on rows_BlockType {\n        id\n        uid\n        title\n        slug\n        uri\n        enabled\n        archived\n        siteId\n        siteSettingsId\n        language\n        searchScore\n        trashed\n        status\n        dateCreated\n        dateUpdated\n        fieldId\n        ownerId\n        typeId\n        sortOrder\n        heading\n        unityMark\n        serviceDetailColumns {\n          remoteTypeName: __typename\n          ... on serviceDetailColumns_column_BlockType {\n            id\n            uid\n            title\n            slug\n            uri\n            enabled\n            archived\n            siteId\n            siteSettingsId\n            language\n            searchScore\n            trashed\n            status\n            dateCreated\n            dateUpdated\n            fieldId\n            ownerId\n            typeId\n            typeHandle\n            sortOrder\n            service {\n              remoteTypeName: __typename\n              sourceId\n              siteId\n            }\n            heading\n            text\n          }\n        }\n      }\n    }\n    ... on serviceDetailColumns_column_BlockType {\n      ... on serviceDetailColumns_column_BlockType {\n        id\n        uid\n        title\n        slug\n        uri\n        enabled\n        archived\n        siteId\n        siteSettingsId\n        language\n        searchScore\n        trashed\n        status\n        dateCreated\n        dateUpdated\n        fieldId\n        ownerId\n        typeId\n        typeHandle\n        sortOrder\n        service {\n          remoteTypeName: __typename\n          sourceId\n          siteId\n        }\n        heading\n        text\n      }\n    }\n    ... on flexibleContent_subscriptionForm_BlockType {\n      ... on flexibleContent_subscriptionForm_BlockType {\n        id\n        uid\n        title\n        slug\n        uri\n        enabled\n        archived\n        siteId\n        siteSettingsId\n        language\n        searchScore\n        trashed\n        status\n        dateCreated\n        dateUpdated\n        fieldId\n        ownerId\n        typeId\n        typeHandle\n        sortOrder\n        heading\n        subheading\n      }\n    }\n    ... on flexibleContent_currentStatus_BlockType {\n      ... on flexibleContent_currentStatus_BlockType {\n        id\n        uid\n        title\n        slug\n        uri\n        enabled\n        archived\n        siteId\n        siteSettingsId\n        language\n        searchScore\n        trashed\n        status\n        dateCreated\n        dateUpdated\n        fieldId\n        ownerId\n        typeId\n        typeHandle\n        sortOrder\n        heading\n        text\n        statusHeading\n        statusValue\n        imagePrimary {\n          remoteTypeName: __typename\n          remoteId: id\n          siteId\n        }\n        imageSecondary {\n          remoteTypeName: __typename\n          remoteId: id\n          siteId\n        }\n      }\n    }\n    ... on flexibleContent_informationGrid_BlockType {\n      ... on flexibleContent_informationGrid_BlockType {\n        id\n        uid\n        title\n        slug\n        uri\n        enabled\n        archived\n        siteId\n        siteSettingsId\n        language\n        searchScore\n        trashed\n        status\n        dateCreated\n        dateUpdated\n        fieldId\n        ownerId\n        typeId\n        typeHandle\n        sortOrder\n        heading\n        lead\n        text\n        informationGridColumns {\n          remoteTypeName: __typename\n          ... on informationGridColumns_TableRow {\n            col1\n            heading\n            col2\n            text\n          }\n        }\n        image {\n          remoteTypeName: __typename\n          remoteId: id\n          siteId\n        }\n        backgroundColour\n      }\n    }\n    ... on flexibleContent_contactUs_BlockType {\n      ... on flexibleContent_contactUs_BlockType {\n        id\n        uid\n        title\n        slug\n        uri\n        enabled\n        archived\n        siteId\n        siteSettingsId\n        language\n        searchScore\n        trashed\n        status\n        dateCreated\n        dateUpdated\n        fieldId\n        ownerId\n        typeId\n        typeHandle\n        sortOrder\n        heading\n        text\n        options {\n          remoteTypeName: __typename\n          ... on options_BlockType {\n            id\n            uid\n            title\n            slug\n            uri\n            enabled\n            archived\n            siteId\n            siteSettingsId\n            language\n            searchScore\n            trashed\n            status\n            dateCreated\n            dateUpdated\n            fieldId\n            ownerId\n            typeId\n            sortOrder\n            icon {\n              remoteTypeName: __typename\n              remoteId: id\n              siteId\n            }\n            linkTo {\n              remoteTypeName: __typename\n              ... on linkField_Link {\n                ariaLabel\n                customText\n                element {\n                  remoteTypeName: __typename\n                  ... on Element {\n                    remoteTypeName: __typename\n                  }\n                  ... on home_home_Entry {\n                    sourceId\n                    siteId\n                  }\n                  ... on flexibleContent_heroCards_BlockType {\n                    remoteTypeName: __typename\n                  }\n                  ... on cards_BlockType {\n                    remoteTypeName: __typename\n                  }\n                  ... on flexibleContent_textAndImages_BlockType {\n                    remoteTypeName: __typename\n                  }\n                  ... on flexibleContent_imageBanner_BlockType {\n                    remoteTypeName: __typename\n                  }\n                  ... on flexibleContent_servicesCarousel_BlockType {\n                    remoteTypeName: __typename\n                  }\n                  ... on flexibleContent_features_BlockType {\n                    remoteTypeName: __typename\n                  }\n                  ... on flexibleContent_featuresPanel_BlockType {\n                    remoteTypeName: __typename\n                  }\n                  ... on flexibleContent_featureCards_BlockType {\n                    remoteTypeName: __typename\n                  }\n                  ... on flexibleContent_video_BlockType {\n                    remoteTypeName: __typename\n                  }\n                  ... on flexibleContent_callToAction_BlockType {\n                    remoteTypeName: __typename\n                  }\n                  ... on flexibleContent_careProfessionals_BlockType {\n                    remoteTypeName: __typename\n                  }\n                  ... on flexibleContent_budgetGraph_BlockType {\n                    remoteTypeName: __typename\n                  }\n                  ... on flexibleContent_reviewsCarousel_BlockType {\n                    remoteTypeName: __typename\n                  }\n                  ... on reviews_BlockType {\n                    remoteTypeName: __typename\n                  }\n                  ... on flexibleContent_textBlock_BlockType {\n                    remoteTypeName: __typename\n                  }\n                  ... on flexibleContent_partnerCards_BlockType {\n                    remoteTypeName: __typename\n                  }\n                  ... on partners_BlockType {\n                    remoteTypeName: __typename\n                  }\n                  ... on flexibleContent_bCorp_BlockType {\n                    remoteTypeName: __typename\n                  }\n                  ... on flexibleContent_pricing_BlockType {\n                    remoteTypeName: __typename\n                  }\n                  ... on levelCard_BlockType {\n                    remoteTypeName: __typename\n                  }\n                  ... on flexibleContent_contentColumns_BlockType {\n                    remoteTypeName: __typename\n                  }\n                  ... on textColumns_BlockType {\n                    remoteTypeName: __typename\n                  }\n                  ... on flexibleContent_accordionPanel_BlockType {\n                    remoteTypeName: __typename\n                  }\n                  ... on items_BlockType {\n                    remoteTypeName: __typename\n                  }\n                  ... on flexibleContent_leadHeading_BlockType {\n                    remoteTypeName: __typename\n                  }\n                  ... on flexibleContent_leadText_BlockType {\n                    remoteTypeName: __typename\n                  }\n                  ... on flexibleContent_serviceDetail_BlockType {\n                    remoteTypeName: __typename\n                  }\n                  ... on rows_BlockType {\n                    remoteTypeName: __typename\n                  }\n                  ... on serviceDetailColumns_column_BlockType {\n                    remoteTypeName: __typename\n                  }\n                  ... on flexibleContent_subscriptionForm_BlockType {\n                    remoteTypeName: __typename\n                  }\n                  ... on flexibleContent_currentStatus_BlockType {\n                    remoteTypeName: __typename\n                  }\n                  ... on flexibleContent_informationGrid_BlockType {\n                    remoteTypeName: __typename\n                  }\n                  ... on flexibleContent_contactUs_BlockType {\n                    remoteTypeName: __typename\n                  }\n                  ... on options_BlockType {\n                    remoteTypeName: __typename\n                  }\n                  ... on flexibleContent_linkCards_BlockType {\n                    remoteTypeName: __typename\n                  }\n                  ... on serviceCategories_default_Entry {\n                    sourceId\n                    siteId\n                  }\n                  ... on pages_flexibleContent_Entry {\n                    sourceId\n                    siteId\n                  }\n                  ... on searchResults_searchResults_Entry {\n                    sourceId\n                    siteId\n                  }\n                  ... on pages_basic_Entry {\n                    sourceId\n                    siteId\n                  }\n                  ... on flexibleContentBasic_richText_BlockType {\n                    remoteTypeName: __typename\n                  }\n                  ... on flexibleContentBasic_image_BlockType {\n                    remoteTypeName: __typename\n                  }\n                  ... on servicesIndex_servicesIndex_Entry {\n                    sourceId\n                    siteId\n                  }\n                  ... on newsIndex_newsIndex_Entry {\n                    sourceId\n                    siteId\n                  }\n                  ... on newsArticle_default_Entry {\n                    sourceId\n                    siteId\n                  }\n                  ... on eventsIndex_eventsIndex_Entry {\n                    sourceId\n                    siteId\n                  }\n                  ... on eventsArticle_default_Entry {\n                    sourceId\n                    siteId\n                  }\n                  ... on serviceItems_default_Entry {\n                    sourceId\n                    siteId\n                  }\n                  ... on newsCategories_default_Entry {\n                    sourceId\n                    siteId\n                  }\n                  ... on images_Asset {\n                    remoteId: id\n                    siteId\n                  }\n                  ... on icons_Asset {\n                    remoteId: id\n                    siteId\n                  }\n                  ... on User {\n                    remoteId: id\n                    siteId\n                  }\n                  ... on General_GlobalSet {\n                    remoteId: id\n                    siteId\n                  }\n                  ... on seo_GlobalSet {\n                    remoteId: id\n                    siteId\n                  }\n                  ... on main_Node {\n                    remoteId: id\n                    siteId\n                  }\n                  ... on footerPrimary_Node {\n                    remoteId: id\n                    siteId\n                  }\n                  ... on footerSecondary_Node {\n                    remoteId: id\n                    siteId\n                  }\n                }\n                target\n                text\n                title\n                type\n                url\n              }\n            }\n          }\n        }\n        includeDivider\n      }\n    }\n    ... on options_BlockType {\n      ... on options_BlockType {\n        id\n        uid\n        title\n        slug\n        uri\n        enabled\n        archived\n        siteId\n        siteSettingsId\n        language\n        searchScore\n        trashed\n        status\n        dateCreated\n        dateUpdated\n        fieldId\n        ownerId\n        typeId\n        sortOrder\n        icon {\n          remoteTypeName: __typename\n          remoteId: id\n          siteId\n        }\n        linkTo {\n          remoteTypeName: __typename\n          ... on linkField_Link {\n            ariaLabel\n            customText\n            element {\n              remoteTypeName: __typename\n              ... on Element {\n                remoteTypeName: __typename\n              }\n              ... on home_home_Entry {\n                sourceId\n                siteId\n              }\n              ... on flexibleContent_heroCards_BlockType {\n                remoteTypeName: __typename\n              }\n              ... on cards_BlockType {\n                remoteTypeName: __typename\n              }\n              ... on flexibleContent_textAndImages_BlockType {\n                remoteTypeName: __typename\n              }\n              ... on flexibleContent_imageBanner_BlockType {\n                remoteTypeName: __typename\n              }\n              ... on flexibleContent_servicesCarousel_BlockType {\n                remoteTypeName: __typename\n              }\n              ... on flexibleContent_features_BlockType {\n                remoteTypeName: __typename\n              }\n              ... on flexibleContent_featuresPanel_BlockType {\n                remoteTypeName: __typename\n              }\n              ... on flexibleContent_featureCards_BlockType {\n                remoteTypeName: __typename\n              }\n              ... on flexibleContent_video_BlockType {\n                remoteTypeName: __typename\n              }\n              ... on flexibleContent_callToAction_BlockType {\n                remoteTypeName: __typename\n              }\n              ... on flexibleContent_careProfessionals_BlockType {\n                remoteTypeName: __typename\n              }\n              ... on flexibleContent_budgetGraph_BlockType {\n                remoteTypeName: __typename\n              }\n              ... on flexibleContent_reviewsCarousel_BlockType {\n                remoteTypeName: __typename\n              }\n              ... on reviews_BlockType {\n                remoteTypeName: __typename\n              }\n              ... on flexibleContent_textBlock_BlockType {\n                remoteTypeName: __typename\n              }\n              ... on flexibleContent_partnerCards_BlockType {\n                remoteTypeName: __typename\n              }\n              ... on partners_BlockType {\n                remoteTypeName: __typename\n              }\n              ... on flexibleContent_bCorp_BlockType {\n                remoteTypeName: __typename\n              }\n              ... on flexibleContent_pricing_BlockType {\n                remoteTypeName: __typename\n              }\n              ... on levelCard_BlockType {\n                remoteTypeName: __typename\n              }\n              ... on flexibleContent_contentColumns_BlockType {\n                remoteTypeName: __typename\n              }\n              ... on textColumns_BlockType {\n                remoteTypeName: __typename\n              }\n              ... on flexibleContent_accordionPanel_BlockType {\n                remoteTypeName: __typename\n              }\n              ... on items_BlockType {\n                remoteTypeName: __typename\n              }\n              ... on flexibleContent_leadHeading_BlockType {\n                remoteTypeName: __typename\n              }\n              ... on flexibleContent_leadText_BlockType {\n                remoteTypeName: __typename\n              }\n              ... on flexibleContent_serviceDetail_BlockType {\n                remoteTypeName: __typename\n              }\n              ... on rows_BlockType {\n                remoteTypeName: __typename\n              }\n              ... on serviceDetailColumns_column_BlockType {\n                remoteTypeName: __typename\n              }\n              ... on flexibleContent_subscriptionForm_BlockType {\n                remoteTypeName: __typename\n              }\n              ... on flexibleContent_currentStatus_BlockType {\n                remoteTypeName: __typename\n              }\n              ... on flexibleContent_informationGrid_BlockType {\n                remoteTypeName: __typename\n              }\n              ... on flexibleContent_contactUs_BlockType {\n                remoteTypeName: __typename\n              }\n              ... on options_BlockType {\n                remoteTypeName: __typename\n              }\n              ... on flexibleContent_linkCards_BlockType {\n                remoteTypeName: __typename\n              }\n              ... on serviceCategories_default_Entry {\n                sourceId\n                siteId\n              }\n              ... on pages_flexibleContent_Entry {\n                sourceId\n                siteId\n              }\n              ... on searchResults_searchResults_Entry {\n                sourceId\n                siteId\n              }\n              ... on pages_basic_Entry {\n                sourceId\n                siteId\n              }\n              ... on flexibleContentBasic_richText_BlockType {\n                remoteTypeName: __typename\n              }\n              ... on flexibleContentBasic_image_BlockType {\n                remoteTypeName: __typename\n              }\n              ... on servicesIndex_servicesIndex_Entry {\n                sourceId\n                siteId\n              }\n              ... on newsIndex_newsIndex_Entry {\n                sourceId\n                siteId\n              }\n              ... on newsArticle_default_Entry {\n                sourceId\n                siteId\n              }\n              ... on eventsIndex_eventsIndex_Entry {\n                sourceId\n                siteId\n              }\n              ... on eventsArticle_default_Entry {\n                sourceId\n                siteId\n              }\n              ... on serviceItems_default_Entry {\n                sourceId\n                siteId\n              }\n              ... on newsCategories_default_Entry {\n                sourceId\n                siteId\n              }\n              ... on images_Asset {\n                remoteId: id\n                siteId\n              }\n              ... on icons_Asset {\n                remoteId: id\n                siteId\n              }\n              ... on User {\n                remoteId: id\n                siteId\n              }\n              ... on General_GlobalSet {\n                remoteId: id\n                siteId\n              }\n              ... on seo_GlobalSet {\n                remoteId: id\n                siteId\n              }\n              ... on main_Node {\n                remoteId: id\n                siteId\n              }\n              ... on footerPrimary_Node {\n                remoteId: id\n                siteId\n              }\n              ... on footerSecondary_Node {\n                remoteId: id\n                siteId\n              }\n            }\n            target\n            text\n            title\n            type\n            url\n          }\n        }\n      }\n    }\n    ... on flexibleContent_linkCards_BlockType {\n      ... on flexibleContent_linkCards_BlockType {\n        id\n        uid\n        title\n        slug\n        uri\n        enabled\n        archived\n        siteId\n        siteSettingsId\n        language\n        searchScore\n        trashed\n        status\n        dateCreated\n        dateUpdated\n        fieldId\n        ownerId\n        typeId\n        typeHandle\n        sortOrder\n        primaryCard\n        secondaryCard\n        backgroundColour\n      }\n    }\n    ... on serviceCategories_default_Entry {\n      sourceId\n      siteId\n    }\n    ... on pages_flexibleContent_Entry {\n      sourceId\n      siteId\n    }\n    ... on searchResults_searchResults_Entry {\n      sourceId\n      siteId\n    }\n    ... on pages_basic_Entry {\n      sourceId\n      siteId\n    }\n    ... on flexibleContentBasic_richText_BlockType {\n      ... on flexibleContentBasic_richText_BlockType {\n        id\n        uid\n        title\n        slug\n        uri\n        enabled\n        archived\n        siteId\n        siteSettingsId\n        language\n        searchScore\n        trashed\n        status\n        dateCreated\n        dateUpdated\n        fieldId\n        ownerId\n        typeId\n        typeHandle\n        sortOrder\n        body\n      }\n    }\n    ... on flexibleContentBasic_image_BlockType {\n      ... on flexibleContentBasic_image_BlockType {\n        id\n        uid\n        title\n        slug\n        uri\n        enabled\n        archived\n        siteId\n        siteSettingsId\n        language\n        searchScore\n        trashed\n        status\n        dateCreated\n        dateUpdated\n        fieldId\n        ownerId\n        typeId\n        typeHandle\n        sortOrder\n        image {\n          remoteTypeName: __typename\n          remoteId: id\n          siteId\n        }\n      }\n    }\n    ... on servicesIndex_servicesIndex_Entry {\n      sourceId\n      siteId\n    }\n    ... on newsIndex_newsIndex_Entry {\n      sourceId\n      siteId\n    }\n    ... on newsArticle_default_Entry {\n      sourceId\n      siteId\n    }\n    ... on eventsIndex_eventsIndex_Entry {\n      sourceId\n      siteId\n    }\n    ... on eventsArticle_default_Entry {\n      sourceId\n      siteId\n    }\n    ... on serviceItems_default_Entry {\n      sourceId\n      siteId\n    }\n    ... on newsCategories_default_Entry {\n      sourceId\n      siteId\n    }\n    ... on images_Asset {\n      remoteId: id\n      siteId\n    }\n    ... on icons_Asset {\n      remoteId: id\n      siteId\n    }\n    ... on User {\n      remoteId: id\n      siteId\n    }\n    ... on General_GlobalSet {\n      remoteId: id\n      siteId\n    }\n    ... on seo_GlobalSet {\n      remoteId: id\n      siteId\n    }\n    ... on main_Node {\n      remoteId: id\n      siteId\n    }\n    ... on footerPrimary_Node {\n      remoteId: id\n      siteId\n    }\n    ... on footerSecondary_Node {\n      remoteId: id\n      siteId\n    }\n  }\n}\n",
  "variables": { "limit": 100, "offset": 0 },
  "operationName": "LIST_footerSecondary_Node"
}

$_GET = [
    'p' => 'api'
]

$_FILES = []

$_COOKIE = []

$_SERVER = [
    'PATH' => '/container/application/node_modules/.bin:/container/application/public/node_modules/.bin:/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin'
    'HOSTNAME' => 'edc251920006'
    'ENVIRONMENT' => 'production'
    'APP_ID' => 'CraftCMS--09618fa0-49e5-49d0-a5df-3d130b04c5a8'
    'SECURITY_KEY' => '••••••••••••••••••••••••••••••••'
    'DB_DRIVER' => 'mysql'
    'DB_PASSWORD' => '••••••••••••••••••••••••••••••••••••••••'
    'DB_SERVER' => 'mysql57'
    'DB_DATABASE' => 'frankie004'
    'DB_USER' => 'frankie004'
    'PRIMARY_SITE_URL' => 'https://frankie004gatsbymain.gatsbyjs.io'
    'DB_PORT' => '3306'
    'PREVIEW_SITE_URL' => 'https://preview-frankie004gatsbymain.gtsb.io'
    'GATSBY_PREVIEW_WEBHOOK' => 'https://webhook.gatsbyjs.com/hooks/data_source/e0c698aa-019c-42f3-81d0-9c48481d16d0'
    'GATSBY_BUILD_WEBHOOK' => 'https://webhook.gatsbyjs.com/hooks/data_source/publish/e0c698aa-019c-42f3-81d0-9c48481d16d0'
    'GATSBY_WEBHOOK_URL' => 'https://webhook.gatsbyjs.com/hooks/data_source/publish/e0c698aa-019c-42f3-81d0-9c48481d16d0'
    'MAILGUN_DOMAIN' => 'mail.batch.dev'
    'MAILGUN_API_KEY' => '••••••••••••••••••••••••••••••••••••'
    'MAILGUN_ENDPOINT' => 'https://api.mailgun.net/v3/mail.batch.dev'
    'CRAFT_URL' => 'https://frankie.batch.dev'
    'VIRTUAL_HOST' => 'frankie.batch.dev,www.frankie.batch.dev'
    'CERT_NAME' => 'frankie.batch.dev'
    'TZ' => 'Pacific/Auckland'
    'NPM_CONFIG_LOGLEVEL' => 'info'
    'NODE_VERSION' => '14.15.4'
    'DEBIAN_FRONTEND' => 'noninteractive'
    'HOME' => '/var/www'
    'LC_CTYPE' => 'C.UTF-8'
    'SUPERVISOR_ENABLED' => '1'
    'SUPERVISOR_SERVER_URL' => 'unix:///var/run/supervisor.sock'
    'SUPERVISOR_PROCESS_NAME' => 'php'
    'SUPERVISOR_GROUP_NAME' => 'php'
    'USER' => 'www-data'
    'SCRIPT_NAME' => '/index.php'
    'REQUEST_URI' => '/api'
    'QUERY_STRING' => 'p=api'
    'REQUEST_METHOD' => 'POST'
    'SERVER_PROTOCOL' => 'HTTP/1.1'
    'GATEWAY_INTERFACE' => 'CGI/1.1'
    'REDIRECT_QUERY_STRING' => 'p=api'
    'REDIRECT_URL' => '/api'
    'REMOTE_PORT' => '53644'
    'SCRIPT_FILENAME' => '/var/www/html/public/index.php'
    'SERVER_ADMIN' => 'webmaster@localhost'
    'CONTEXT_DOCUMENT_ROOT' => '/var/www/html/public'
    'CONTEXT_PREFIX' => ''
    'REQUEST_SCHEME' => 'http'
    'DOCUMENT_ROOT' => '/var/www/html/public'
    'REMOTE_ADDR' => '34.133.157.193'
    'SERVER_PORT' => '80'
    'SERVER_ADDR' => '172.18.0.58'
    'SERVER_NAME' => 'frankie.batch.dev'
    'SERVER_SOFTWARE' => 'Apache'
    'SERVER_SIGNATURE' => ''
    'HTTP_ACCEPT_ENCODING' => 'gzip,deflate'
    'HTTP_USER_AGENT' => 'node-fetch/1.0 (+https://github.com/bitinn/node-fetch)'
    'HTTP_ACCEPT' => '*/*'
    'HTTP_AUTHORIZATION' => 'Bearer CZEez0D85dvVWqREqCGuPcrkJyUErHbY'
    'CONTENT_TYPE' => 'application/json'
    'CONTENT_LENGTH' => '98605'
    'HTTP_X_FORWARDED_PORT' => '443'
    'HTTP_X_FORWARDED_SSL' => 'on'
    'HTTP_X_FORWARDED_PROTO' => 'https'
    'HTTP_X_FORWARDED_FOR' => '34.133.157.193'
    'HTTP_CONNECTION' => 'close'
    'HTTP_HOST' => 'frankie.batch.dev'
    'proxy-nokeepalive' => '1'
    'HTTPS' => 'on'
    'REDIRECT_STATUS' => '200'
    'REDIRECT_HTTPS' => 'on'
    'FCGI_ROLE' => 'RESPONDER'
    'PHP_SELF' => '/index.php'
    'REQUEST_TIME_FLOAT' => 1637099337.2792
    'REQUEST_TIME' => 1637099337
]

What might be causing this: String cannot represent value: [] error?

Steps to reproduce

  1. Clear the cache using gatsby clean
  2. Build once using gatsby build
  3. Build a second time using gatsby build

Additional info

  • Craft version: 3.6.4
  • PHP version: 7.2.5
  • Craft Plugins & versions:
    • "craftcms/cms": "^3.6.4",
    • craftcms/commerce": "^3.4",
    • "craftcms/gatsby-helper": "^1.0",
    • "craftcms/mailgun": "1.4.3",
    • "craftcms/redactor": "2.8.8",
    • "doublesecretagency/craft-cpcss": "2.3.1",
    • "sebastianlenz/linkfield": "^2.0.0-beta.12",
    • "verbb/events": "^1.4",
    • "verbb/navigation": "1.4.22",
    • "verbb/super-table": "2.6.8",
    • "vlucas/phpdotenv": "^3.4.0"
  • Gatsby Plugin & versions
    • Gatbsy : 3.10.2
    • gatsby -source-craft: 2.0.2

image querying problem

Description

I'm getting an error in Gatsby with certain image files that I've uploaded as a Craft asset that I'm trying to pull in to use as local files. Here's an example:

ERROR #85901  GRAPHQL

There was an error in your GraphQL query:

Unexpected error value: "url passed to createRemoteFileNode is either missing or not a proper web uri: http://alserkalnew.demoyourprojects.com/assets/images/Phantasmagoria’s-Illumination-in-DisenchantmentCurated-by-Dr.-Arshiya-Lokhandwala_installation_5e6de3d3163d4.png"

  230 |       id
  237 |       headerImage {
  238 |         __typename
  239 |         ... on Craft_editorialAssets_Asset {
> 240 |           cardImage: localFile {
      |           ^
  241 |             publicURL
  242 |             childImageSharp {
  243 |               fixed(width: 290) {
  244 |                 src
  245 |                 ...GatsbyImageSharpFixed

That particular image URL works – you can click on it. However, it's triggering an error – this is fine in dev, though it crashes Netlify builds.

I'm not 100% sure that this is a gatsby-source-craft issue! And I suspect it might not be! But errors seem to pop up with mildly strange characters in filenames, like that right single-quote in that file name. When I re-upload the image and give it a safe name ("resavedphantasmagoria.png"), there's no problem with the build. Is this some kind of weird encoding issue? Or do I have something dumb not set in my Craft config?

Thanks so much!

Additional info

  • Craft version: Craft Pro 3.6.7
  • PHP version: 7.2.24
  • Database driver & version: MySQL 5.7.33
  • Plugins & versions: Gatsby Helper 1.0.0-beta.2, Redator 2.8.5

Unable to filter by siteId in gatsby

Description

I've added a second site to a fresh Craft 3.5.15.1 install for fr-CA localization. (siteId = 2) But so far I've been unable to query that from the gatsby side. I've tried manually deleting the .cache folder, running gatsby clean, and restarting both the PHP/Nginx servers as well as gatsby develop.

Here's the query working within Craft's GraphiQL:

craft-graphiql

{
  entries(section: "blogPosts", siteId: "2") {
    title
    ... on blogPosts_blogPosts_Entry {
      richTextDefault
    }	
  }
}

and the query I tried in Gatsby's GraphiQL

gatsby-graphiql
:

query MyQuery {
  allCraftBlogPostsBlogPostsEntry(filter: {siteId: {eq: 2}}) {
    nodes {
      title
      richTextDefault
    }
  }
}

Steps to reproduce

  1. Create a second site with a different locale
  2. Set up your sections and fields to support the new locale
  3. Create and enable an entry to be published under this locale
  4. restart everything just to make sure.
  5. try to query the new entry data from the gatsby side using a siteId filter

Additional info

  • Craft version: 3.5.15.1
  • PHP version: PHP 7.3.24 (cli) (built: Nov 5 2020 22:49:15) ( NTS )
  • Database driver & version: mysql 5.7
  • Plugins & versions:
    -- Gatsby: only gatsby-source-craft
    -- Craft:
    "born05/craft-assetusage": "2.2.0.1",
    "craftcms/aws-s3": "1.2.11",
    "craftcms/cms": "^3.5.15.1",
    "craftcms/gatsby-helper": "1.0.0-beta.1",
    "craftcms/redactor": "2.8.3",
    "doublesecretagency/craft-inventory": "2.1.1",
    "fruitstudios/linkit": "1.1.12.1",
    "nystudio107/craft-retour": "3.1.42",
    "nystudio107/craft-seomatic": "3.3.22",
    "spicyweb/craft-fieldlabels": "1.3.1.2",
    "spicyweb/craft-neo": "2.8.13",
    "vlucas/phpdotenv": "^3.4.0",
    "yiisoft/yii2-redis": "~2.0.0"

Query to return `lastUpdateTime` can be mistakenly cached

In reference to this line:

query: 'query craftState { configVersion lastUpdateTime }',

It appears the results of this query can be cached, meaning the timestamp of the latest updated returned can be inaccurate. The follow-on effect of this is that the list of changed and deleted nodes fetched here:

query: `query nodeChanges {
nodesUpdatedSince (since: "${localContentUpdateTime}") { nodeId nodeType siteId}
nodesDeletedSince (since: "${localContentUpdateTime}") { nodeId nodeType siteId}
}`,

will be too long and have references to nodes that were never present in the initial build. Finally, arriving at this line:
await sourceNodeChanges(config, { nodeEvents });

will throw an error, since references in the list of nodeEvents pointing to nodes not existing locally will throw errors like this:
Screen Shot 2020-11-15 at 20 20 21

Suggestion would be to potentially inject a random variable in the query to ensure up to date results?

The `sourceNodes` lifecycle fails after upgrading to the 2.0.2 patch.

Description

Upgrading from 2.0.1 to 2.0.2 results in an error during gatsby develop which causes all queries to return null:

"gatsby-source-craft" threw an error while running the sourceNodes lifecycle:

Failed to execute query LIST_about_about_Entry.
Errors:
Unknown argument "status" on field "entry" of type "Query".

  468 |     if (remoteConfigVersion !== localConfigVersion || !localContentUpdateTime) {
  469 |         reporter.info("Cached content is unavailable or outdated, sourcing _all_ nodes.");
> 470 |         await sourceAllNodes(config);
      |         ^
  471 |     }
  472 |     else {
  473 |         reporter.info(`Craft config version has not changed since last sourcing. Checking for content changes since "${localContentUpdateTime}".`);

File: node_modules/gatsby-source-craft/gatsby-node.js:470:9



  Error: Failed to execute query LIST_about_about_Entry.
  Errors:
  Unknown argument "status" on field "entry" of type "Query".

Steps to reproduce

  1. upgrade gatsby-source-craft from any version to 2.0.2
  2. run gatsby develop

Additional info

  • Craft version: Craft Pro 3.6.17
  • PHP version: 7.3.27
  • Database driver & version: MySQL 5.5.5
  • Plugins & versions: Gatsby Helper 1.0.3

Asset does not have an id

On some builds I get this error. I'm not sure how this is possible.

The field "CraftuploadsAsset.id." was explicitly defined as non-nullable via the schema customization API (by yourself or a plugin/theme). This means that this field is not optional and you have to define a value. If this is not your desired behavior and you defined the schema yourself, go to "createTypes" in gatsby-node.js. If you're using a plugin/theme, you can learn more here on how to fix field types:
  361 | fragment AssetFragment on Craft_uploads_Asset {
> 362 |   id
      |   ^
  363 |   focalPoint
  364 |   url
  365 |   height
  366 |   width
  367 |   title
  368 |   caption
  369 |   assetLinkUrl
  370 |   attribution
  371 | }

How is this even possible that an Asset does not have an id?

The error appears on random entries which do have assets.

I'm using:

"gatsby-source-craft": "2.0.2",

Has anyone seen this before. How can I mitigate this?

Cache always invalidated

I'm working on upgrading from Gatsby 2 to 3 and decided to try this instead of the graphql source plugin. Every time i restart the develop script the cache is invalidated and I wait 10+ minutes to rebuild.

I've tried eliminating plugins and simplifying the project but have made no progress. I can try to create a minimal reproduction later but I wanted to report this in case there was something I'm missing that could solve this issue.

Here's what I'm seeing each time I start the project up:

info One or more of your plugins have changed since the last time you ran Gatsby. As
a precaution, we're deleting your site's cache to ensure there's no stale data.
...
info Cached content is unavailable or outdated, sourcing _all_ nodes.

Error while sourcing with "Allow listing non-live and otherwise inactive elements." disabled in Schema

Description

Guess who's back.. na na na.. back again ;)

Gatsby build fails when this is unchecked,

 ERROR #11321  PLUGIN

"gatsby-source-craft" threw an error while running the sourceNodes lifecycle:

Failed to execute query LIST_forhandlere_forhandler_Entry.
Errors:
Unknown argument "status" on field "entry" of type "Query".

  510 |     if (remoteConfigVersion !== localConfigVersion || !localContentUpdateTime) {
  511 |         reporter.info("Cached content is unavailable or outdated, sourcing _all_ nodes.");
> 512 |         await sourceAllNodes(config);
      |         ^
  513 |     }
  514 |     else {
  515 |         reporter.info(`Craft config version has not changed since last sourcing. Checking for content changes since "${localContentUpdateTime}".`);

File: node_modules/gatsby-source-craft/gatsby-node.js:512:9

From Craft's web.log:

2021-12-02 11:40:33 [-][-][-][error][GraphQL\Error\Error] Unknown argument "status" on field "entry" of type "Query".

GraphQL (2:35)
1: query NODE_produkter_glasdore_Entry($id: [QueryArgument], $siteId: [QueryArgument]) {
2:   entry(id: $id, siteId: $siteId, status: null) {
                                     ^
3:     remoteTypeName: __typename

Steps to reproduce

  1. Uncheck "Allow listing non-live and otherwise inactive elements." in your Craft GQL schema settings
  2. Source data
  3. Pull your hair out ;)

Additional info

  • Craft version: 3.7.23
  • PHP version: 7.3.31
  • Database driver & version: MySQL 5.6.51
  • Plugins & versions:
    Cloner 1.2.2
    Freeform 3.12.7
    Gatsby Helper 1.1.0
    Redactor 2.8.8
    Smith 1.1.14
    Spoon 3.6.1
    Sprout Notes 2.2.3
    Tags 1.0.9

Deprecation Warnings in Craft when sourcing data

Description

Craft show the following errors under "Deprecation Warnings" when running the source plugin.

43 	Deprecation error: Elements’ getSourceId() method has been deprecated. Use getCanonicalId() instead.
Called from /home/somedomain.com/tsakansdzy/public_html/vendor/craftcms/cms/src/base/Element.php:2323

42 	craft\elements\Entry::getSourceId()
Called from /home/somedomain.com/tsakansdzy/public_html/vendor/yiisoft/yii2/base/Component.php:140

41 	craft\elements\Entry::__get("sourceId")
Called from /home/somedomain.com/tsakansdzy/public_html/vendor/craftcms/cms/src/base/Element.php:1736

40 	craft\elements\Entry::__get("sourceId")
Called from /home/somedomain.com/tsakansdzy/public_html/vendor/craftcms/cms/src/gql/base/ObjectType.php:73

39 	craft\gql\types\elements\Entry::resolve(craft\elements\Entry, [], ["conditionBuilder" => craft\gql\ElementQueryConditionBuilder, "argumentManager" => craft\gql\ArgumentManager], GraphQL\Type\Definition\ResolveInfo)
Called from /home/somedomain.com/tsakansdzy/public_html/vendor/craftcms/cms/src/gql/types/elements/Element.php:54

38 	craft\gql\types\elements\Entry::resolve(craft\elements\Entry, [], ["conditionBuilder" => craft\gql\ElementQueryConditionBuilder, "argumentManager" => craft\gql\ArgumentManager], GraphQL\Type\Definition\ResolveInfo)
Called from /home/somedomain.com/tsakansdzy/public_html/vendor/craftcms/cms/src/gql/types/elements/Entry.php:65

...

Steps to reproduce

  1. Install this plugin
  2. Source some data

Additional info

  • Craft version: 3.7.23
  • PHP version: 7.3.31
  • Database driver & version: MySQL 5.6.51
  • Plugins & versions:
    Cloner 1.2.2
    Freeform 3.12.7
    Gatsby Helper 1.0.9.1
    Redactor 2.8.8
    Smith 1.1.14
    Spoon 3.6.1
    Sprout Notes 2.2.3
    Tags 1.0.9

Error while running the createResolvers lifecycle

Description

I got the error when running either gatsby develop or gatsby build

"gatsby-source-craft" threw an error while running the createResolvers lifecycle:

Cannot read property 'name' of undefined

  382 |     const ifaceName = loadedPluginOptions.typePrefix + 'AssetInterface';
  383 |     const iface = intermediateSchema.getType(ifaceName);
> 384 |     const possibleTypes = intermediateSchema.getPossibleTypes(iface);
      |                                              ^
  385 |     const resolvers = {};
  386 |     for (const assetType of possibleTypes) {
  387 |         resolvers[assetType] = {

Steps to reproduce

  1. Install and configure the plugin as per the doc
{
    resolve: `gatsby-source-craft`,
    options: {},
},
  1. Either run gatsby develop or gatsby build

Additional info

  • Craft version: 3.5.17.1
  • PHP version: 7.4.13
  • Database driver & version: MYSQL 5.7.28
  • Plugins & versions: 1.0.0-beta.2

Pending entries cause incremental updates to fail

Description

We have been experiencing intermittent failures with our builds. (See craftcms/gatsby-helper#13 for context and details.) Part of the issue was resolved by changes to gatsby-helper. However, the issue persisted and I was able to track it down to occurring only on incremental builds which had a pending entry.

PR and details incoming...

Steps to reproduce

Suggestion: set a resolution to use [email protected]. This will give better error reporting.

  1. Run gatsby build to ensure a cache is built. This will trigger an incremental build on the next step.
  2. Create a "pending" status entry. (i.e. It must have a future publish date but be published.)
  3. Run gatsby build again. This time it should fail with Error: Node "[entry_type_from_step2]" with id "{ __typename: '[entry_type_from_step2]', id: '[entry_id_from_step2]', siteId: '1' }" is nullish.

More examples for custom fragments

Description

It would be great if the documentation had more examples of custom fragments that show how to use popular plugins like:

  • Link Field: Show us how to resolve the element field for multiple element types
  • Verbb's Navigation: Show us how to resolve the element field for multiple element types
  • SEOMatic: Show us how to include the seomatic field on entries with the asArray: true param

If you were to add these examples, it would also be great if you had end-to-end examples that show how to use this data in Gatsby.

I feel like i'm too often missing all the different pieces, and hitting roadblocks. Mind that this is partially due to migrating from the old GraphQL source plugin.

Craft Image Transforms in Gatsby

Description

I have tried every combo that is outlined by the documentation to get Image transforms to work and nothing seems to be working:

Option 1:
When I add my own directory for fragments with a test image transform, it causes the entire Craft schema to not work. Gatsby is not able to find ANY of the types that the source plugin usually provides. I have also tried both fragment types inside of my .graphql file:

fragment resizedImage on Craft_projectSlide_BlockType {
  featuredImage {
    resized: url @transform(width: 1400)
  }
}
fragment Craft_digitalOcean_Asset on Craft_digitalOcean_Asset {
  frontPageThumb: url(width: 400, height: 400)
}

Option 2:
Added the transform directive along side my other fragments inside a component. Gatsby errors saying that the directive does not exist.

Option 3:
I tried adding the transform field directly to the digitalOcean_Asset type inside of a component also does not work. When trying this it throws an error that url does not have an argument width or any of the other possible arguments.

Steps to reproduce

  1. Updated the fragmentsDir option and observe no Craft types available

Additional info

The craft-fragments folder inside of the .cache of node_modules is empty after sourcing.

As a test I went into the default folder set by the plugin for fragments and added my transform fragment there. When I start up the site the same error occurs as when I add a custom directory for fragment. The entire Craft schema breaks and no types are available within Gatsby GraphQL schema

  • Craft version: 3.5.17.1
  • PHP version: 7.4
  • Database driver & version:
  • Plugins & versions:
    "gatsby": "^2.29.3",
    "gatsby-source-craft": "^1.0.0-beta.2",
    "gatsby-source-graphql": "^2.5.3",

Neo matrix data not retrieved after a depth of 3 items

Description

Hi,

I've hit an issue with this plugin where it seems like the depth of the graph is limited.

I'm currently using a neo matrix, which was working fine with the original gatsby-source-graphql plugin.

This is what my query looks like in Gatsby

query MyQuery ($id:StringQueryOperatorInput) {
  craftWorkshopsWorkshopEntry(id: $id) {
    neoLP {
      ... on Craft_neoLP_ctas_BlockType {
         horizontalAlignment
         children {
	    ... on Craft_neoLP_cta_BlockType {
		label
          }
        }
      }
      
      ... on Craft_neoLP_columns_BlockType {
        children {
          ... on Craft_neoLP_column_BlockType {
            rightColumnFirstMobile
            children {
              ... on Craft_neoLP_ctas_BlockType {
                children {
                  ... on Craft_neoLP_cta_BlockType {
                    pageLink
                  }
                }
              }
              ... on Craft_neoLP_richtext_BlockType {
                richtext
              }
            }
          }
        }
      }
    }
  }
}

The matrix (ctas) block when placed at the root of the matrix returns its data correctly.

Here is a sample response.

{
  "data": {
    "craftWorkshopsWorkshopEntry": {
      "neoLP": [
        {
          "children": [
            {
              "rightColumnFirstMobile": false,
              "children": [
                {
                  "richtext": null
                },
                {
                  "children": []
                },
                {
                  "richtext": null
                },
                {
                  "richtext": null
                },
                {
                  "children": []
                },
                {
                  "richtext": null
                },
                {
                  "children": []
                }
              ]
            },
            {
              "rightColumnFirstMobile": false,
              "children": []
            }
          ]
        },
        {
          "horizontalAlignment": "left",
          "children": [
            {
              "label": "Test"
            }
          ]
        }
      ]
    }
  }
}

Rebuilding this within CraftCMS using the graphiql UI works fine and so does the standard gatsby-source-graphql plugin.

Steps to reproduce

  1. Create a neo matrix with a depth of more than 3 (not 100% sure what depth breaks)
  2. See if data is returned

Additional info

  • Craft version: 3.5.18
  • PHP version: 7.2.24
  • Database driver & version: MySQL 5.5.5
  • Plugins & versions: Neo (2.8.5)

Thanks for any help you can provide

site only returns {data: {ping: pong}}

I'm trying to get this to work on a Craft site and keep running into an error in Gatsby:

ERROR #11321  PLUGIN

"gatsby-source-craft" threw an error while running the onPreBootstrap lifecycle:

Invalid or incomplete introspection result. Ensure that you are passing "data" property of introspection response and no "errors" was
returned alongside: { ping: "pong" }

  36 | async function getSchema() {
  37 |     if (!schema) {
> 38 |         schema = await loadSchema(execute);
     |                  ^
  39 |     }
  40 |     return schema;
  41 | }

File: node_modules/gatsby-source-craft/gatsby-node.js:38:18

GraphiQL works fine from inside Craft; but I can't get anything into Gatsby. Any ideas what could be going on here? I will note that if I do a curl from the command line:

curl -H "Content-Type: application/graphql" --data-urlencode "query={configVersion}" [url]

I don't get back the value for "configVersion" but instead '{"data":{"ping":"pong"}}'. Maybe this isn't a gatsby-source-craft issue? But I'm at a loss.

Custom type field is missing from Gatsby

Description

I have added a custom type field named imgix to AssetInterface through the TypeManager::EVENT_DEFINE_GQL_TYPE_FIELDS event like this:

 Event::on(
            TypeManager::class,
            TypeManager::EVENT_DEFINE_GQL_TYPE_FIELDS,
            function(DefineGqlTypeFieldsEvent $event) {
                if (in_array($event->typeName, self::GQL_ELEMENT_INTERFACES, true)) {
                    $event->fields['imgix'] = [
                        'name' => 'imgix',
                        'type' => ImgixInterface::getType(),
                        'args' => ImgixArguments::getArguments(),
                        'resolve' => ImgixResolver::class . '::resolve',
                        'description' => 'This query is used to query for Imgix meta data.',
                    ];
                }
            });

This has been working well with the gatsby-source-graphql source, and I have been using it like this:

imgix(maxWidth: 800, maxHeight: 800, quality: 100) {...}

After installing gatsby-source-craft, I still see the custom type (imgix) on AssetInterface, but it doesn't list any of the params.

image

Now, I read the section about Integrating Third-Party Content, but this seems to apply only to source nodes?

Do I need to do anything else for the source to pick them up?

Additional info

  • Craft version: 3.6

won't work if Craft "gqlTypePrefix" config is set.

Description

If you try to set "gqlTypePrefix" to "Craft_" on a working Craft + Gatsby implementation, you get:

"gatsby-source-craft" threw an error while running the createSchemaCustomization lifecycle:

Field "id" at path "RequiredEntryFields" has no parent type. This may indicate that your remote schema had changed and
your fragment "RequiredEntryFields" must be updated.

  524 |     const schema = await getSchema();
  525 |     const gatsbyNodeTypes = await getGatsbyNodeTypes();
> 526 |     const documents = await compileNodeQueries({
      |                             ^
  527 |         schema,
  528 |         gatsbyNodeTypes,
  529 |         customFragments: await collectFragments(),

File: node_modules/gatsby-source-craft/gatsby-node.js:526:29
  • Craft version: 3.7.22
  • PHP version: 8.0
  • Database driver & version: mysql
  • Plugins & versions: just this one

FetchError ETIMEDOUT prevents build, no way to increase timeout?

Description

Recently I started getting FetchError: request to https://my-craft-url.com/api failed, reason: connect ETIMEDOUT <IP>:443 almost all the time when running a development/production build of my project locally (Builds in CI pipeline seem to work fine so far).

I searched for a way to increase the connection timeout with node-fetch etc... but couldn't find a way to do it. I also tried to reduce the concurrency option (set it to 1 for example) but this didn't help either.

I have the error with gatsby v3 as well as gatsby v4 (via the gatsby-v4 branch.

So I was wondering if there is some way how I can increase the connection timeout for the connections used by this plugin?

Error

info Clearing previous fragments.
info Clearing previous fragments.
info Writing default fragments.
info Clearing previous fragments.
info Clearing previous fragments.
info Writing default fragments.
info Writing default fragments.
info Writing default fragments.
info Clearing previous fragments.
info Clearing previous fragments.
info Writing default fragments.
info Writing default fragments.
info Clearing previous fragments.
info Writing default fragments.
success fetching camera_Tag - 25.180s

 ERROR #11321  PLUGIN

"gatsby-source-craft" threw an error while running the sourceNodes lifecycle:

request to  https://my-craft-url.com/api failed, reason: connect ETIMEDOUT <IP>:443



  FetchError: request to https://my-craft-url.com/api failed, reason: connect ETIMEDOUT <IP>:443
  
  - index.js:1483 ClientRequest.<anonymous>
    [my-gatsby-project]/[node-fetch]/lib/index.js:1483:11
  
  - node:events:390 ClientRequest.emit
    node:events:390:28
  
  - node:domain:475 ClientRequest.emit
    node:domain:475:12
  
  - node:_http_client:447 TLSSocket.socketErrorListener
    node:_http_client:447:9
  
  - node:events:390 TLSSocket.emit
    node:events:390:28
  
  - node:domain:475 TLSSocket.emit
    node:domain:475:12
  
  - destroy:157 emitErrorNT
    node:internal/streams/destroy:157:8
  
  - destroy:122 emitErrorCloseNT
    node:internal/streams/destroy:122:3
  
  - task_queues:83 processTicksAndRejections
    node:internal/process/task_queues:83:21
  

not finished source and transform nodes - 26.243s
not finished fetching photo_photo_Entry - 25.868s
not finished fetching photos_Asset - 25.938s
not finished fetching film_Tag - 25.860s
not finished fetching lens_Tag - 25.879s
not finished fetching photoTags_Tag - 25.872s
not finished fetching projectTags_Tag - 25.884s
not finished fetching User - 25.959s

error "gatsby-source-craft" threw an error while running the sourceNodes lifecycle:

Hey Guys,

Not sure if this is the right place to post this as it only happens when Verbbs Formie plugin is installed in CraftCMS, but once the plugin tries to source the Schema, it fails with the following errors.

error "gatsby-source-craft" threw an error while running the sourceNodes lifecycle:

Failed to execute query LIST_home_home_Entry.
Errors:
Fields "limit" conflict because they return conflicting types String and Boolean. Use different aliases on the fields to fetch both if this was intentional.
 
Fields "defaultValue" conflict because they return conflicting types String and Boolean. Use different aliases on the fields to fetch both if this was intentional.

Fields "defaultValue" conflict because they return conflicting types DateTime and String. Use different aliases on the fields to fetch both if this was intentional.

Fields "defaultValue" conflict because they return conflicting types String and DateTime. Use different aliases on the fields to fetch both if this was intentional.

Fields "multiple" conflict because they return conflicting types Boolean and String. Use different aliases on the fields to fetch both if this was intentional.

Field "settings" of type "FormSettingsInterface" must have a sub selection.

The previous list goes for long and then it finally fails with the following message

error Missing onError handler for invocation 'building-schema', error was 'Error: Type with name "FormSettingsInterface" does not exists'.

Querying the field via CraftCMS's graphql explorer works just fine.

Additional info

Using

  System:
    OS: macOS 10.15.7
    CPU: (8) x64 Intel(R) Core(TM) i7-4770HQ CPU @ 2.20GHz
    Shell: 3.2.57 - /bin/bash
  Binaries:
    Node: 14.15.1 - ~/.nvm/versions/node/v14.15.1/bin/node
    Yarn: 1.22.10 - /usr/local/bin/yarn
    npm: 6.14.8 - ~/.nvm/versions/node/v14.15.1/bin/npm
  Languages:
    Python: 2.7.16 - /usr/bin/python
  Browsers:
    Chrome: 87.0.4280.67
    Firefox: 82.0.2
    Safari: 14.0.1
  npmPackages:
    gatsby: 2.27.0 => 2.27.0
    gatsby-plugin-env-variables: ^2.0.0 => 2.0.0
    gatsby-plugin-postcss: ^2.1.13 => 2.3.13
    gatsby-plugin-purgecss: ^4.0.1 => 4.0.1
    gatsby-plugin-react-helmet: ^3.6.0 => 3.6.0
    gatsby-plugin-react-helmet-canonical-urls: ^1.4.0 => 1.4.0
    gatsby-plugin-react-svg: ^3.0.0 => 3.0.0
    gatsby-plugin-resolve-src: ^2.1.0 => 2.1.0
    gatsby-plugin-styled-components: ^3.6.0 => 3.6.0
    gatsby-plugin-styled-jsx: ^3.6.0 => 3.6.0
    gatsby-source-craft: 1.0.0-beta.2 => 1.0.0-beta.2
  npmGlobalPackages:
    gatsby-cli: 2.15.0

CraftCMS Additional info

Craft CMS 3.5.16
PHP version | 7.4.10

PLUGINS
Formie | 1.3.2
Gatsby Helper 1.0.0-beta.2

Using a nested block (NEO Field) in a Gatsby GraphQL query throws error message.

Description

Experimenting with using Neo with Gatsby. When I introduce a child block into the query I get an error message, (only in Gatsby)

"Abstract type \"Craft_NeoBlockInterface\" must resolve to an Object type at runtime for field \"Craft_contentBuilder_calloutSection_BlockType.children\". Either the \"Craft_NeoBlockInterface\" type should provide a \"resolveType\" function or each possible type should provide an \"isTypeOf\" function."

Steps to reproduce

  1. Create a block type which contains another block type. In this case we are using an image block inside a callout section block.
    image
  2. In Gatsby GraphiQL explorer I make a simple test query (which works correctly as expected in the CraftCMS GraphiQL explorer).
query MyQuery {
  allCraftEntryInterface(filter: {sectionHandle: {eq: "products"}}, limit: 1) {
    nodes {
      id
      ... on Craft_products_products_Entry {
        title
        contentBuilder {
          ... on Craft_contentBuilder_calloutSection_BlockType {
            disableAddToCartButton
            children {
              ... on Craft_contentBuilder_imageBlock_BlockType {
                image {
                  url
                }
              }
            }
          }
        }
      }
    }
  }
}
  1. Output:
  "errors": [
    {
      "message": "Abstract type \"Craft_NeoBlockInterface\" must resolve to an Object type at runtime for field \"Craft_contentBuilder_calloutSection_BlockType.children\". Either the \"Craft_NeoBlockInterface\" type should provide a \"resolveType\" function or each possible type should provide an \"isTypeOf\" function.",
      "locations": [
        {
          "line": 10,
          "column": 13
        }
      ],
      "path": [
        "allCraftEntryInterface",
        "nodes",
        0,
        "contentBuilder",
        0,
        "children",
        0
      ],
      "stack": [
        "GraphQLError: Abstract type \"Craft_NeoBlockInterface\" must resolve to an Object type at runtime for field \"Craft_contentBuilder_calloutSection_BlockType.children\". Either the \"Craft_NeoBlockInterface\" type should provide a \"resolveType\" function or each possible type should provide an \"isTypeOf\" function.",
        "    at ensureValidRuntimeType (/Users/wedo/Sites/Clients/Emson/Granitestone/node_modules/graphql/execution/execute.js:685:11)",
        "    at completeAbstractValue (/Users/wedo/Sites/Clients/Emson/Granitestone/node_modules/graphql/execution/execute.js:680:42)",
        "    at completeValue (/Users/wedo/Sites/Clients/Emson/Granitestone/node_modules/graphql/execution/execute.js:584:12)",
        "    at /Users/wedo/Sites/Clients/Emson/Granitestone/node_modules/graphql/execution/execute.js:620:25",
        "    at Array.map (<anonymous>)",
        "    at safeArrayFrom (/Users/wedo/Sites/Clients/Emson/Granitestone/node_modules/graphql/jsutils/safeArrayFrom.js:36:23)",
        "    at completeListValue (/Users/wedo/Sites/Clients/Emson/Granitestone/node_modules/graphql/execution/execute.js:607:53)",
        "    at completeValue (/Users/wedo/Sites/Clients/Emson/Granitestone/node_modules/graphql/execution/execute.js:572:12)",
        "    at resolveField (/Users/wedo/Sites/Clients/Emson/Granitestone/node_modules/graphql/execution/execute.js:472:19)",
        "    at executeFields (/Users/wedo/Sites/Clients/Emson/Granitestone/node_modules/graphql/execution/execute.js:292:18)",
        "    at collectAndExecuteSubfields (/Users/wedo/Sites/Clients/Emson/Granitestone/node_modules/graphql/execution/execute.js:748:10)",
        "    at completeObjectValue (/Users/wedo/Sites/Clients/Emson/Granitestone/node_modules/graphql/execution/execute.js:738:10)",
        "    at completeAbstractValue (/Users/wedo/Sites/Clients/Emson/Granitestone/node_modules/graphql/execution/execute.js:680:10)",
        "    at completeValue (/Users/wedo/Sites/Clients/Emson/Granitestone/node_modules/graphql/execution/execute.js:584:12)",
        "    at /Users/wedo/Sites/Clients/Emson/Granitestone/node_modules/graphql/execution/execute.js:620:25",
        "    at Array.map (<anonymous>)"
      ]
    }
  ],
  "data": {
    "allCraftEntryInterface": {
      "nodes": [
        {
          "id": "products_products_Entry:33:1",
          "title": "GraniteStone 5 Qt. Gradient Stock Pot",
          "contentBuilder": [
            {
              "disableAddToCartButton": false,
              "children": [
                null
              ]
            }
          ]
        }
      ]
    }
  },
  "extensions": {}
}

Other information

  • Neo version: Neo 2.9.8
  • Craft version: Craft CMS 3.6.15
  • (if multi-site) What is the affected Neo field's propagation method: Only Save to site they were created in
  • Is eager-loading used? no

image
image

$id is not defined

Just started using this plugin, and it seems to be working really well. Was just wondering about this console error I saw, any idea why that's showing up?

image

Structure entries in Gatsby do not return "children"

Description

Structure entries do not return "children" as they do in the Craft GraphQL implementation.

I understand this might not be a bug but a platform limitation in transforming Craft entries into the Gatsby node graph but I feel it would be helpful to a lot of people if this functionality was available.

Steps to reproduce

Any query on structure elements shows the children prop and all the associated interfaces but does not yield any results.

query MyQuery {
  allCraftStructuredPagesContentPageEntry {
    nodes {
      children {
        id
      }
    }
  }
}
{
  "data": {
    "allCraftStructuredPagesContentPageEntry": {
      "nodes": [
        {
          "children": []
        },
        {
          "children": []
        }
    ]
}

Additional info

  • Craft version: 3.6.16
  • Gatsby helper: 1.0.3

Only absolute URLs are supported ERROR

Description

Upon running gatsby develop, im getting the following error

ERROR #11321  PLUGIN

"gatsby-source-craft" threw an error while running the onPreBootstrap lifecycle:

Only absolute URLs are supported

  237 |         headers['X-Craft-Token'] = previewToken;
  238 |     }
> 239 |     const res = await fetch(craftGqlUrl, {
      |                       ^
  240 |         method: "POST",
  241 |         body: JSON.stringify({ query, variables, operationName }),
  242 |         headers

File: node_modules/gatsby-source-craft/gatsby-node.js:239:23

  TypeError: Only absolute URLs are supported

ENV variables are set as specified in the DOCS

CRAFTGQL_TOKEN=_VOTTQWBP1bx19gQLE1gBynzz
CRAFTGQL_URL=https://testsite.test/api

and the plugin is listed in gatsby-config.js

Additional info

  • Craft version: Craft Pro 3.5.15.1
  • PHP version: 7.4.10
  • Database driver & version: MySQL 5.7.32
  • Plugins & versions:
  • Node v11.15.0

Deleted Entry Not Being Removed

Description

Whenever an entry is deleted from a structure or channel. Gatsby is not notified of new content changes on any subsequent builds. A full cache clear is required to render the site without the deleted entry.

Steps to reproduce

  1. Delete Entry
  2. Trigger Build via deploy hook
  3. Notice deleted entry is still within the Gatsby Nodes

Additional info

GATSBY_EXPERIMENTAL_PAGE_BUILD_ON_DATA_CHANGES=true gatsby build --log-pages

12:48:05 PM: info Checking Craft config version.
12:48:06 PM: info Craft config version has not changed since last sourcing. Checking for content changes since "2021-06-21 16:38:55".
12:48:06 PM: info No content changes found.
  • Craft version: 3.5.17.1
  • PHP version: 7.4.13
  • Database driver & version: MySQL 8.0.22
  • Plugins & versions:
    Gatsby Helper | 1.0.1
    "gatsby-source-craft": "^1.0.0",

Live Preview 404 when attempting to update

Description

I currently have a "preview" server that is running gatsby develop on Digital Ocean's App Platform. This runs fine with no issues and also has the ENABLE_GATSBY_REFRESH_ENDPOINT set to true. I have taken the baseUrl for this app and added it to the Gatsby Helper settings within my Craft CMS install as stated in the documentation. When I am using the Live Preview feature within the CMS, everytime I make an update the AJAX request to trigger an update within Gatsby results in a 404 Error, nothing is logged by Gatsby, and no changes are made.

After some digging I went into the Gatsby Helper settings and have changed the URL there from the {baseUrl} to {baseUrl}/__refresh which is the direct url of webhook endpoint for Gatsby to trigger an update.

After making this change, I know get a 200 status back on the update request but do not see any changes reflected in the Live Preview.

Request Payload:

id: 3
operation: "update"
siteId: 1
token: "asdjkasjdh23122"
typeName: "home_home_Entry"

Response:
The browser is currently showing no response available to this request, unsure if that is expected or not.

Server Logs:
On the "preview" server I can see the logs firing whenever this update request is made however there is an error happening during the sourceNodes lifecycle, pasted below:

FetchError: invalid json response body at https://gencon-admin-staging.thesmithy.io/actions/graphql/api reason: Unexpected token < in JSON at position 4

This does not seem to break the app as the preview remains properly rendered.

Note: For some reason the only endpoint that will work for me is actions/graphql/api. Even after updating my routes.php file, both api and graphql/api do not work. Maybe it's a server thing? (Separate issue for me to sort out). I actually get the invalid json response body error as stated above. My assumption is that its getting the 404 html page back. But since this endpoint works to initially source the website I am not sure why this breaks on update.

Steps to reproduce

  1. Add baseurl for preview to Gatsby Helper
  2. Open Live Preview on an entry
  3. Observer no changes to content and 404 in console

Additional info

Craft version: 3.5.17.1
PHP version: 7.4
Database driver & version:
Plugins & versions:
"gatsby": "^2.29.3",
"gatsby-source-craft": "^1.0.0-beta.2",
"gatsby-source-graphql": "^2.5.3",

"gatsby-source-craft" threw an error while running the sourceNodes lifecycle

Description

I'm frequently encountering the following error on Gatsby Cloud when making changes in CraftCMS:

"gatsby-source-craft" threw an error while running the sourceNodes lifecycle:

Cannot read property 'map' of null

488 |         // Create the sourcing node events
  489 |         const nodeEvents = [
> 490 |             ...updatedNodes.map(entry => {
      |                             ^
  491 |                 return {
  492 |                     eventName: 'UPDATE',
  493 |                     remoteTypeName: entry.nodeType,

The only difference from a normal setup is that I have registered a custom source node type to support Craft Commerce Products by doing the following:

Event::on(
    SourceNodes::class,
    SourceNodes::EVENT_REGISTER_SOURCE_NODE_TYPES,
    function (RegisterSourceNodeTypesEvent $event) {
        $event->types[] = [
            'node' => 'product',
            'list' => 'products',
            'filterArgument' => 'type',
            'filterTypeExpression' => '(.+)_Product',
            'targetInterface' => ProductInterface::getName(),
        ];
    }
);

The build succeeds if I clear the cache and perform a fresh build from Gatsby Cloud (which is not an ideal solution for my client!).

I'll have a good dig through over the weekend and see if I can nail down what's actually causing this error.

Steps to reproduce

Not sure at the moment, it seems to happen after making a few changes to entries after a fresh build.

Additional info

  • Craft version: 3.6.15
  • PHP version: 7.4.10
  • Database driver & version: MySQL 8.0.21
  • Plugins & versions:
    • Amazon SES - 1.3.3
    • Craft Commerce - 3.3.2
    • Gatsby Helper - 1.0.3
    • Mailchimp Subscribe - 3.0.3
    • MatrixMate 1.2.7
    • Redactor - 2.8.7
    • SEOmatic - 3.3.42
    • Stripe for Craft Commerce - 2.3.2.1
    • Super Table - 2.6.8

Screen Shot 2021-07-01 at 8 58 23 PM

Empty string to createTypes action

Description

I just set up a fresh install of Craft and Gatsby. After configuring both the front-end and back end and starting up the server I get the below error:

Encountered an error parsing the provided GraphQL type definitions:
Syntax Error: Unexpected <EOF>

> 1 |
    | ^

not finished createSchemaCustomization - 0.042s

I checked out the plugin code and it looks like the createTypes(typeDefs) is getting an empty string as an argument. I currently have no queries set up in Gatsby so not sure if this is an issue here. Was hoping I could spin it up and use the Graphiql tool to make sure things were set up correctly.

Steps to reproduce

  1. run gatsby develop
  2. Observe error

Additional info

For some reason I have never had the routes config setting work on my graphql apis, not sure if it is something that Laravel Forge prevents or not. But I have gatsby pointing at the /actions/graphql/api endpoint. Happy to provide any other info as well!

  • Craft version: 3.5.17.1
  • PHP version: 7.4
  • Database driver & version: MySQL 8
  • Plugins & versions:
"gatsby-source-craft": "^1.0.0-beta.2",
"craftcms/gatsby-helper": "1.0.0-beta.2",

Sourcing data error

Description

I get errors when trying to local develop and I don't get any nodes back. All fields are checked in Craft so that shouldn't be the problem that the nodes are not getting back.

Steps to reproduce

  1. gatsby develop

Additional info

  • Craft version: Craft Pro 3.6.16
  • PHP version: 7.4.14
  • Database driver & version: MySQL 5.7.29
  • gatsby-source-craft@^2.0.2
 ERROR #11321  PLUGIN

"gatsby-source-craft" threw an error while running the sourceNodes lifecycle:

Failed to execute query LIST_Homepage_Homepage_Entry.
Errors:
No GraphQL query was supplied

  468 |     if (remoteConfigVersion !== localConfigVersion || !localContentUpdateTime) {
  469 |         reporter.info("Cached content is unavailable or outdated, sourcing _all_ nodes.");
> 470 |         await sourceAllNodes(config);
      |         ^
  471 |     }
  472 |     else {
  473 |         reporter.info(`Craft config version has not changed since last sourcing. Checking for content       
changes since "${localContentUpdateTime}".`);

File: node_modules\gatsby-source-craft\gatsby-node.js:470:9



  Error: Failed to execute query LIST_Homepage_Homepage_Entry.
  Errors:
  No GraphQL query was supplied

  - paginate.ts:60 Object.paginate
    [emson-brands-shopify]/[gatsby-source-craft]/[gatsby-graphql-source-toolkit]/src/source-nodes/fetch-nodes/pagina    te.ts:60:13

  - task_queues.js:97 processTicksAndRejections
    internal/process/task_queues.js:97:5

  - fetch-lists.ts:61 fetchNodeList
    [emson-brands-shopify]/[gatsby-source-craft]/[gatsby-graphql-source-toolkit]/src/source-nodes/fetch-nodes/fetch-    lists.ts:61:20

  - fetch-lists.ts:36 Object.fetchAllNodes
    [emson-brands-shopify]/[gatsby-source-craft]/[gatsby-graphql-source-toolkit]/src/source-nodes/fetch-nodes/fetch-    lists.ts:36:24

  - create-nodes.ts:13 Object.createNodes
    [emson-brands-shopify]/[gatsby-source-craft]/[gatsby-graphql-source-toolkit]/src/source-nodes/node-actions/creat    e-nodes.ts:13:20

  - async Promise.all

  - source-all-nodes.ts:20 sourceAllNodes
    [emson-brands-shopify]/[gatsby-source-craft]/[gatsby-graphql-source-toolkit]/src/source-nodes/source-all-nodes.t    s:20:3

  - gatsby-node.js:470 Object.exports.sourceNodes
    [emson-brands-shopify]/[gatsby-source-craft]/gatsby-node.js:470:9

  - api-runner-node.js:434 runAPI
    [emson-brands-shopify]/[gatsby]/src/utils/api-runner-node.js:434:16

Regression?: "gatsby-source-craft" threw an error while running the sourceNodes lifecycle bug

Description

This issue was fixed (#50) but has now reappeared. Somehow as soon as Gatsby tries to use the cache to do a build this error occurs. We do not have multisite enabled this time. Site is built on Netlify with "Essential Gatsby" plugin installed.

The only reason we use this plugin instead of "gatsby-source-graphql" is for incremental builds but it seems to just break instead. I also see this line in the official documentation about missing data with incremental builds,

This means that sometimes incremental sourcing can make your site have some obsolete content. For this reason, it is recommended to do a full page build (by cleaning the Gatsby caches beforehand) before deploying the built site.

could it be related? We can't possibly ask the customer to clear the cache when they change something on the site :)

@andris-sevcenko any ideas? We would be happy to give you access to the server again if you need to look around.

8:54:58 AM: info Checking Craft config version.
8:54:59 AM: info Craft config version has not changed since last sourcing. Checking for content changes since "2021-11-23 19:49:33".
8:55:00 AM: error "gatsby-source-craft" threw an error while running the sourceNodes lifecycle:
8:55:00 AM: Cannot read properties of null (reading 'map')
8:55:00 AM:   488 |         // Create the sourcing node events
8:55:00 AM:   489 |         const nodeEvents = [
8:55:00 AM: > 490 |             ...updatedNodes.map(entry => {
8:55:00 AM:       |                             ^
8:55:00 AM:   491 |                 return {
8:55:00 AM:   492 |                     eventName: 'UPDATE',
8:55:00 AM:   493 |                     remoteTypeName: entry.nodeType,
8:55:00 AM: 
8:55:00 AM: 
8:55:00 AM:   TypeError: Cannot read properties of null (reading 'map')
8:55:00 AM:   
8:55:00 AM:   - gatsby-node.js:490 Object.exports.sourceNodes
8:55:00 AM:     [repo]/[gatsby-source-craft]/gatsby-node.js:490:29
8:55:00 AM:   
8:55:00 AM:   - task_queues:96 processTicksAndRejections
8:55:00 AM:     node:internal/process/task_queues:96:5
8:55:00 AM:   
8:55:00 AM:   - api-runner-node.js:430 runAPI
8:55:00 AM:     [repo]/[gatsby]/src/utils/api-runner-node.js:430:16
8:55:00 AM:   
8:55:00 AM: 
8:55:00 AM: not finished source and transform nodes - 2.259s
8:55:00 AM: ​
8:55:00 AM: ────────────────────────────────────────────────────────────────
8:55:00 AM:   "build.command" failed                                        
8:55:00 AM: ────────────────────────────────────────────────────────────────

Steps to reproduce

  1. Make a change to random entry
  2. Build site on Netlify
  3. Sometimes it works, sometimes it don't and we get this issue

Additional info

  • Craft version: 3.7.21
  • PHP version: 7.3.31
  • Database driver & version: MySQL 5.6.51
  • Plugins & versions:
    Cloner 1.2.2
    Formie 1.4.26
    Gatsby Helper 1.0.7
    Redactor 2.8.8
    Smith 1.1.14
    Spoon 3.6.1
    Sprout Notes 2.2.3
    Tags 1.0.9

Error: Interface field Craft_FormInterface.fields expected but Craft_Form does not provide it.

Description

Getting an error using the Verbb's Formie Plugin after upgrading to the latest version of gatsby-source-craft.


Missing onError handler for invocation 'extracting-queries', error was 'Error: Interface field Craft_FormInterface.fields expected but Craft_Form does not provide it.'. Stacktrace was 'Error: Interface field
Craft_FormInterface.fields expected but Craft_Form does not provide it.
    at assertValidSchema (/Users/user/Development/website/node_modules/graphql/type/validate.js:71:11)
    at validate (/Users/user/Development/panda/node_modules/graphql/validation/validate.js:54:35)
    at extractOperations (/Users/user/Development/website/node_modules/gatsby/src/query/query-compiler.js:212:20)
    at processQueries (/Users/user/Development/website/node_modules/gatsby/src/query/query-compiler.js:171:45)
    at compile (/Users/user/Development/website/node_modules/gatsby/src/query/query-compiler.js:82:19)
    at updateStateAndRunQueries (/Users/user/Development/website/node_modules/gatsby/src/query/query-watcher.ts:220:40)
    at extractQueries (/Users/user/Development/website/node_modules/gatsby/src/services/extract-queries.ts:18:3)'

  • Formie Plugin version: 1.3.16.1
  • Craft version: Craft CMS 3.6.5.1 Pro
  • Gatsby: 2.32.2
  • PHP version: 8.0.2
  • Database driver & version: MySQL

Allow `CRAFTGQL_URL` to be set via config option

Description

Vercel doesn't support branch environment variables. Instead, there are only 3 default environments "Live", "Preview" and "Local"

Their recommend approach to set per-branch environment variables is to do something like following:

const host =
  process.env.VERCEL_GITHUB_COMMIT_REF === "qa"
    ? process.env.CRAFTGQL_QA_URL
    : process.env.CRAFTGQL_URL;

Unfortunately, this isn't currently supported as CRAFTGQL_URL is hard-coded in the plugin file. I think simply moving this to an override-able option using the environment as a default would solve the issue.

Unable to source nodes! – no such file or directory ...internal-craft-fragments

Description

I can't get this to run. When I gatsby develop or gatsby-build I get the following error.

 ERROR 

Unable to source nodes!


 ERROR #11321  PLUGIN

"gatsby-source-craft" threw an error while running the createSchemaCustomization lifecycle:

ENOENT: no such file or directory, scandir
'/Users/dylan/Sites/wrkshp/node_modules/gatsby-source-craft/.cache/internal-craft-fragments'

I've tried with and without the fragmentsDir option, however that option seems to have no effect.

I have the Gatsby Helper plugin installed. Craft is the current version. "gatsby": "^4.0.2",

Any ideas?

error on build after upgrading to 1.0.2

Description

I have a Craft site that's running an up-to-date Gatsby Helper (1.0.3). I'm still periodically getting crashes on Netlify deploys, which get fixed when I clear the cache and redeploy (what's described here: craftcms/gatsby-helper#13 ). I was going to report an error, but then I took a look at my package.json and realized that my gatsby-source-craft was still at 1.0.0. So I updated to gatsby-source-craft 1.0.2 hoping that this piece of stupidity on my part would fix things.

This is not the case! After updating to 1.0.2, I can't get a build to work either locally or on Netlify. Here's the trace I get running locally:

"gatsby-source-craft" threw an error while running the sourceNodes lifecycle:

Failed to execute query LIST_ourPeople_ourPeople_Entry.
Errors:
Unknown argument "status" on field "entry" of type "Query".

  468 |     if (remoteConfigVersion !== localConfigVersion || !localContentUpdateTime) {
  469 |         reporter.info("Cached content is unavailable or outdated, sourcing _all_ nodes.");
> 470 |         await sourceAllNodes(config);
      |         ^
  471 |     }
  472 |     else {
  473 |         reporter.info(`Craft config version has not changed since last sourcing. Checking for content changes since 
"${localContentUpdateTime}".`);

File: node_modules/gatsby-source-craft/gatsby-node.js:470:9



  Error: Failed to execute query LIST_ourPeople_ourPeople_Entry.
  Errors:
  Unknown argument "status" on field "entry" of type "Query".
  
  - paginate.ts:60 Object.paginate
    [alserkal-designsystem]/[gatsby-graphql-source-toolkit]/src/source-nodes/fetch-nodes/paginate.ts:60:13
  
  - task_queues.js:93 processTicksAndRejections
    internal/process/task_queues.js:93:5
  
  - fetch-lists.ts:61 fetchNodeList
    [alserkal-designsystem]/[gatsby-graphql-source-toolkit]/src/source-nodes/fetch-nodes/fetch-lists.ts:61:20
  
  - fetch-lists.ts:36 Object.fetchAllNodes
    [alserkal-designsystem]/[gatsby-graphql-source-toolkit]/src/source-nodes/fetch-nodes/fetch-lists.ts:36:24
  
  - create-nodes.ts:13 Object.createNodes
    [alserkal-designsystem]/[gatsby-graphql-source-toolkit]/src/source-nodes/node-actions/create-nodes.ts:13:20
  
  - async Promise.all
  
  - source-all-nodes.ts:20 sourceAllNodes
    [alserkal-designsystem]/[gatsby-graphql-source-toolkit]/src/source-nodes/source-all-nodes.ts:20:3
  
  - gatsby-node.js:470 Object.exports.sourceNodes
    [alserkal-designsystem]/[gatsby-source-craft]/gatsby-node.js:470:9
  
  - api-runner-node.js:485 runAPI
    [alserkal-designsystem]/[gatsby]/src/utils/api-runner-node.js:485:16
  

success fetching discoverTheAvenue_discoverTheAvenue_Entry - 4.243s
warn The gatsby-source-craft plugin has generated no Gatsby nodes. Do you need it?

As noted, it looks like nothing's coming in from Craft at all.

If I downgrade to gatsby-source-craft, the whole thing works again (though I'll presumably still get periodically failing builds). Any idea what could be happening?

One thing to note: in my schema in Craft, I have:

Allow listing element drafts
Allow listing element revisions
Allow listing non-live and otherwise inactive elements.

all unchecked.

Steps to reproduce

  1. uninstall working gatsby-source-craft 1.0.0, install gatsby-source-craft 1.0.2
  2. try to build

Additional info

  • Craft version: Craft Pro 3.6.16
  • PHP version: 7.2.24
  • Database driver & version: MySQL 5.5.5
  • Plugins & versions: Gatsby Helper 1.0.3

Sourcing data error

Description

I am getting the error below sporadically. I get this error in ~70% of the builds. The remaining ~30% of the time the build is successful.

Steps to reproduce

  1. Run gatsby build

Additional info

  • Craft version: 3.7.17
  • PHP version: 7.3
  • Database driver & version: NA
  • Plugins & versions:
    Craft composer.json
      "born05/craft-enforcepassword": "1.0.4.2",
      "born05/craft-twofactorauthentication": "2.9.0",
      "craftcms/aws-s3": "1.2.15",
      "craftcms/cms": "3.7.17",
      "craftcms/feed-me": "4.4.0",
      "craftcms/gatsby-helper": "1.0.6",
      "craftcms/mailgun": "1.4.3",
      "craftcms/redactor": "2.8.8",
      "diginov/craft-sentry-logger": "^1.1",
      "nystudio107/craft-retour": "3.1.61",
      "nystudio107/craft-seomatic": "3.4.7",
      "sebastianlenz/linkfield": "2.0.0-rc.1",
      "spicyweb/craft-neo": "2.11.14",
      "verbb/field-manager": "2.2.4",
      "verbb/navigation": "1.4.21",
      "vlucas/phpdotenv": "^3.4.0"
    
    Gatbsy package.json
      "@googlemaps/js-api-loader": "^1.12.2",
      "@tailwindcss/aspect-ratio": "^0.2.1",
      "algoliasearch": "^4.10.5",
      "encodeurl": "^1.0.2",
      "formik": "^2.2.9",
      "gatsby": "^3.11.1",
      "gatsby-plugin-algolia": "^0.22.2",
      "gatsby-plugin-canonical-urls": "^3.14.0",
      "gatsby-plugin-gatsby-cloud": "^2.11.0",
      "gatsby-plugin-google-tagmanager": "^3.14.0",
      "gatsby-plugin-image": "^1.11.0",
      "gatsby-plugin-manifest": "^3.11.0",
      "gatsby-plugin-offline": "^4.11.0",
      "gatsby-plugin-react-helmet": "^4.11.0",
      "gatsby-plugin-robots-txt": "^1.6.10",
      "gatsby-plugin-sharp": "^3.11.0",
      "gatsby-plugin-sitemap": "^4.10.0",
      "gatsby-source-filesystem": "^3.11.0",
      "gatsby-transformer-json": "^3.13.0",
      "gatsby-transformer-sharp": "^3.11.0",
      "mailgun-js": "^0.22.0",
      "prop-types": "^15.7.2",
      "react": "^17.0.1",
      "react-dom": "^17.0.1",
      "react-helmet": "^6.1.0",
      "react-instantsearch-dom": "^6.12.1",
      "react-nl2br": "^1.0.2",
      "react-transition-group": "^4.4.2",
      "use-debounce": "^7.0.0"
    

Stack Trace

 ERROR #11321  PLUGIN

"gatsby-source-craft" threw an error while running the sourceNodes lifecycle:

Failed to execute query LIST_footer_Node.


  468 |     if (remoteConfigVersion !== localConfigVersion || !localContentUpdateTime) {
  469 |         reporter.info("Cached content is unavailable or outdated, sourcing _all_ nodes.");
> 470 |         await sourceAllNodes(config);
      |         ^
  471 |     }
  472 |     else {
  473 |         reporter.info(`Craft config version has not changed since last sourcing. Checking for content changes since "${localContentUpdateTime}".`);

File: node_modules/gatsby-source-craft/gatsby-node.js:470:9



  Error: Failed to execute query LIST_footer_Node.
  
  - paginate.ts:60 Object.paginate
    [forhealth001-gatsby]/[gatsby-graphql-source-toolkit]/src/source-nodes/fetch-nodes/paginate.ts:60:13
  
  - runMicrotasks
  
  - task_queues.js:95 processTicksAndRejections
    internal/process/task_queues.js:95:5
  
  - fetch-lists.ts:61 fetchNodeList
    [forhealth001-gatsby]/[gatsby-graphql-source-toolkit]/src/source-nodes/fetch-nodes/fetch-lists.ts:61:20
  
  - fetch-lists.ts:36 Object.fetchAllNodes
    [forhealth001-gatsby]/[gatsby-graphql-source-toolkit]/src/source-nodes/fetch-nodes/fetch-lists.ts:36:24
  
  - create-nodes.ts:13 Object.createNodes
    [forhealth001-gatsby]/[gatsby-graphql-source-toolkit]/src/source-nodes/node-actions/create-nodes.ts:13:20
  
  - async Promise.all
  
  - source-all-nodes.ts:20 sourceAllNodes
    [forhealth001-gatsby]/[gatsby-graphql-source-toolkit]/src/source-nodes/source-all-nodes.ts:20:3
  
  - gatsby-node.js:470 Object.exports.sourceNodes
    [forhealth001-gatsby]/[gatsby-source-craft]/gatsby-node.js:470:9
  
  - api-runner-node.js:434 runAPI
    [forhealth001-gatsby]/[gatsby]/src/utils/api-runner-node.js:434:16
  

not finished source and transform nodes - 32.244s
not finished fetching pages_default_Entry - 31.443s

Gatsby Cloud builds fail often via webhook and manual rebuilds

Description

Having some very consistent, but inconsistent errors. Most of the time I can run "Clear Cache and Rebuild" and the site will rebuild without error, but not always. Almost always if a rebuild is triggered by webhook it will fail, but very rarely it will succeed.

If I run local builds 'Gatsby Develop' I never get a failure. But those are never triggered by webhook.

image

Error is sometimes:

Triggered by Gatsby Build webhook
Build failed for branch staging
Failed after 0:10

Raw logs
"gatsby-source-craft" threw an error while running the sourceNodes lifecycle:

Cannot read property 'map' of null

488 | // Create the sourcing node events
489 | const nodeEvents = [

490 | ...updatedNodes.map(entry => {
| ^
491 | return {
492 | eventName: 'UPDATE',
493 | remoteTypeName: entry.nodeType,

Error is sometimes:

Triggered by Gatsby Build webhook
Build failed for branch staging
Failed after 0:19

Raw logs
"gatsby-source-craft" threw an error while running the onPreBootstrap lifecycle:

request to https://[redacted].com/api failed, reason: getaddrinfo EAI_AGAIN [redacted].com

For more details see https://gatsby.dev/issue-how-to

Steps to reproduce

  1. Make an edit in the CMS.
  2. Save
  3. Wait for error message in Gatsby Cloud.
    image
    or
    image

Additional info

  • Craft version: 3.7.11
  • PHP version: 7.4.14
  • Database driver & version: MySQL 5.7.29
  • Plugins & versions:
    Gatsby Helper
    1.0.4
    Plugin for enabling support for the Gatsby Craft CMS source plugin.

Google Cloud Storage
1.4.1
Google Cloud Storage integration for Craft CMS

Incognito Field
1.2.0
PlainText drop-in replacement that can be set to disabled, hidden or readonly.

Navigation
1.4.21
A Craft CMS plugin to create navigation menus for your site.

Neo
2.11.9
A Matrix-like field type that uses existing fields

Redactor
2.8.8
Edit rich text content in Craft CMS using Redactor by Imperavi.

SEOmatic
3.4.6
SEOmatic facilitates modern SEO best practices & implementation for Craft CMS 3. It is a turnkey SEO system that is comprehensive, powerful, and flexible.

Webhooks

Additional Info:

image

Built Rendering Engines failed validation failed validation.

Description

I'm trying out the DSG feature in Gatsby 4.22.1 after upgrading from Gatsby 3. But I'm getting this error message. It seems related to the source plugin.

Built Rendering Engines failed validation failed validation.

Please open an issue with a reproduction at https://github.com/gatsbyjs/gatsby/issues/new for more help
failed Validating Rendering Engines - 2.188s

ERROR #98001  WEBPACK
Built Rendering Engines failed validation failed validation.
Please open an issue with a reproduction at https://github.com/gatsbyjs/gatsby/issues/new for more help

  Error: Worker exited before finishing task
  
  - index.js:117 ChildProcess.<anonymous>
    [stm-web-update]/[gatsby-worker]/dist/index.js:117:45
  
  - node:events:394 ChildProcess.emit
    node:events:394:28
  
  - child_process:290 Process.ChildProcess._handle.onexit
    node:internal/child_process:290:12

Steps to reproduce

  1. Upgrade a Gatsby 3 to Gatsby 4
  2. enable DSG rendering in gatsby-node.js createPage({ defer: true,....

Additional info

  • Craft version: 3.7.25.1
  • PHP version: 7.4.30
  • Database driver & version: MySQL 5.5.5
  • Plugins & versions: Gatsby Helper 1.1.2

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.