Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat(gatsby-source-graphql): Add transformSchema option #25048

Merged
merged 10 commits into from
Aug 6, 2020
52 changes: 52 additions & 0 deletions packages/gatsby-source-graphql/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -150,6 +150,58 @@ module.exports = {
}
```

## Custom wrap schema function (advanced)

It's possible to modify the remote schema, via a `customWrapSchemaFn` option which customizes the way the default schema is wrapped before it is merged on the Gatsby schema by the stitching process.

The `customWrapSchemaFn` function gets an object argument with the following fields:

- schema (introspected remote schema)
- link (default link)
- resolver (default resolver)
- defaultTransforms (an array with the default transforms)
- options (plugin options)

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think we need to add a note that the return value is expected to be the final schema used for stitching.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

So, basically, I should only leave this as a reference?

// transform-schema.js
const { wrapSchema } = require(`@graphql-tools/wrap`)
const { linkToExecutor } = require(`@graphql-tools/links`)

const transformSchema = ({
  schema,
  link,
  resolver,
  defaultTransforms,
  options,
}) => {
  return wrapSchema(
    {
      schema,
      executor: linkToExecutor(link),
    },
    defaultTransforms
  )
}

module.exports = transformSchema

I just think that would be a bit vague for anyone else to do something useful without knowing at least how the NamespaceUnderFieldTransform is implemented. But if it's good for you, it's good for me too.

What if I link to this issue somewhere to leave a hint?

Copy link
Contributor

@vladar vladar Jul 21, 2020

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The problem with this feature in general (as I see it) is that it requires a deep understanding of plugin internals and graphql-tools anyways.

I doubt that the example will be enough for anyone to actually use it. People will probably have to dig into the plugin source code anyways. But it may be rather confusing to other people who don't use this feature.

So we need to surface that this feature exists in docs and leave hints on what other knowledge people may need to actually use it.

Adding a link to the original issue makes sense to me though. I think it's ok to go ahead and do this change. Then let's wait for the learning team review.

The return value is expected to be the final schema used for stitching.

Below an example configuration that uses the default implementation (equivalent to not using the `customWrapSchemaFn` option at all):

```js
const { wrapSchema } = require(`@graphql-tools/wrap`)
const { linkToExecutor } = require(`@graphql-tools/links`)

module.exports = {
plugins: [
{
resolve: "gatsby-source-graphql",
options: {
typeName: "SWAPI",
fieldName: "swapi",
url: "https://api.graphcms.com/simple/v1/swapi",
customWrapSchemaFn: ({
schema,
link,
resolver,
defaultTransforms,
options,
}) => {
return wrapSchema(
{
schema,
executor: linkToExecutor(link),
},
defaultTransforms
)
}
},
]
}
```

For details, refer to [https://www.graphql-tools.com/docs/schema-wrapping](https://www.graphql-tools.com/docs/schema-wrapping).

An use case for this feature can be seen in [this issue](https://github.com/gatsbyjs/gatsby/issues/23552).

# Refetching data

By default, `gatsby-source-graphql` will only refetch the data once the server is restarted. It's also possible to configure the plugin to periodically refetch the data. The option is called `refetchInterval` and specifies the timeout in seconds.
Expand Down
39 changes: 25 additions & 14 deletions packages/gatsby-source-graphql/src/gatsby-node.js
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,7 @@ exports.sourceNodes = async (
createSchema,
refetchInterval,
batch = false,
customWrapSchemaFn,
} = options

invariant(
Expand Down Expand Up @@ -95,21 +96,31 @@ exports.sourceNodes = async (
return {}
}

const schema = wrapSchema(
{
schema: introspectionSchema,
executor: linkToExecutor(link),
},
[
new StripNonQueryTransform(),
new RenameTypes(name => `${typeName}_${name}`),
new NamespaceUnderFieldTransform({
typeName,
fieldName,
const defaultTransforms = [
new StripNonQueryTransform(),
new RenameTypes(name => `${typeName}_${name}`),
new NamespaceUnderFieldTransform({
typeName,
fieldName,
resolver,
}),
]

const schema = customWrapSchemaFn
? customWrapSchemaFn({
schema: introspectionSchema,
link,
resolver,
}),
]
)
defaultTransforms,
options,
})
: wrapSchema(
{
schema: introspectionSchema,
executor: linkToExecutor(link),
},
defaultTransforms
)

addThirdPartySchema({ schema })

Expand Down