Inferring fields on the created Node object

Fields that are directly created on the node, meaning fields that are provided through source and transformer plugins (e.g., relativePathsize, and accessTime in nodes of type File), are typically queried through the GraphQL API in a query similar to the following:

node {
  relativePath,
  extension,
  size,
  accessTime
}

These fields are created using the inferObjectStructureFromNodes function in src/schema/infer-graphql-type.js. Based on what kind of object the function is dealing with as it encounters new objects, it can encompass one of the following three subcategories of fields provided on the created Node object:

  • A field provided through a mapping in gatsby-config.js
  • A field having a value provided through a foreign key reference (ending in ___NODE)
  • A plain object or value (such as a string) that is passed in

First, for fields provided through mappings in gatsby-config.js, if the object field being sent for GraphQL type generation is configured in a custom manner in the Gatsby configuration file, it requires special handling. For instance, a typical mapping might look like the following, where we’re mapping a linked type, AuthorYaml, to the MarkdownRemark type so that we make the AuthorYaml.name field available in MarkdownRemark as MarkdownRemark.frontmatter.author:

// gatsby-config.js
mapping: {
  "MarkdownRemark.frontmatter.author": `AuthorYaml.name`,
}

In this situation, the field generation is handled by the inferFromMapping function in src/schema/infer-graphql-type.js. When invoked, the function finds the type to which the identified field is mapped (AuthorYaml), which is known as the linkedType. If a field to link by (linkedField, in this scenario name) is not provided to the function, it defaults to id.

Then, Gatsby declares a new GraphQL field whose type is AuthorYaml (which is searched for within the existing list of gqlTypes). Thereafter, the GraphQL field resolver will acquire the value for the given node (in this example, the author string that should be mapped into the identified field) and conduct a search through all the nodes until it finds one with a matching type and matching field value (i.e., the correct AuthorYaml.name).

Second, for foreign key references, the suffix ___NODE indicates that the value of the field is an id that represents another node present in the Redux store. In this scenario, the inferFromFieldName function in src/schema/infer-graphql-type.js handles the field inference. In this process, which is quite similar to the field mapping process described previously, Gatsby deletes ___NODE from the field name (converting author___NODE into author, for instance). Then it searches for the linkedNode that the id represents in the Redux store (the exampleValue for author, which is an id). Upon identifying the correct node through this foreign key, Gatsby acquires the type in the gqlTypes list via the internal.type value. In addition, Gatsby will accept a linkedField value that adheres to the format nodeFieldName___NODE___linkedFieldName (e.g., author___NODE___name can be provided instead of id).

Then, Gatsby returns a new GraphQL field sharing the same type as that represented by the foreign key. The GraphQL field resolver sifts through all the available Redux nodes until it encounters one with the same id. If the foreign key value is instead an array of ids, then Gatsby will return a GraphQLUnionType; i.e., a union of all linked types represented in the array.

Third, for plain objects or value fields, the inferGraphQLType function in src/schema/infer-graphql-types.js is the default handler. In this scenario, Gatsby creates a GraphQL field object whose type it infers directly by using typeof in JavaScript. For instance, typeof(value) === 'string' would result in the type GraphQLString. As the graphql-js library handles this automatically for Gatsby, there is no need for additional resolvers.

However, if the value provided is an object or an array requiring introspection, Gatsby uses inferObjectStructureFromNodes to recurse through the structure and create new GraphQL fields. Gatsby also creates custom GraphQL types for File (src/schema/types/type-file.js) and Date (src/schema/types/type-date.js): if the value looks like it could be a filename or a date, then Gatsby will return the correct custom type.

NOTE

For more information about how File types are inferred, consult the Gatsby documentation’s schema inference section on File types.


Posted

in

,

by

Tags:

Comments

Leave a Reply

Your email address will not be published. Required fields are marked *