Open thompsonsj opened 1 year ago
graphql-js
typesTODO: Investigate.
Note that the createTypes action also accepts graphql-js types directly, but usually either SDL or Type Builders are the better alternatives.
SDL can be generated from Payload CMS. In the following example, a route is added to server.ts
to generate Gatsby schema customizations on demand:
import { printSchema, GraphQLSchema } from 'graphql'
import buildObjectType from 'payload/dist/graphql/schema/buildObjectType'
// Collection
import Testimonials from './collections/Logos/Testimonials'
app.get('/gatsby-schema-types', async (_, res) => {
const gatsbyNodeType = "PayloadTestimonials"
const testimonials = buildObjectType({
payload,
name: gatsbyNodeType,
parentName: gatsbyNodeType,
fields: Testimonials.fields
})
const schema = new GraphQLSchema({query: testimonials})
const report = printSchema(schema)
res.setHeader('content-type', 'application/json')
res.send(report)
})
This will print the schema for collection fields (as defined).
schema {
query: PayloadTestimonials
}
type PayloadTestimonials {
locales: [PayloadTestimonials_locales!]
name: String!
jobTitle: String
}
"""
Additional definitons....
"""
A more complicated example that:
import { Field } from 'payload/types'
import { buildSchema, printSchema, GraphQLSchema } from 'graphql'
import { mergeSchemas } from '@graphql-tools/schema'
import buildObjectType from 'payload/dist/graphql/schema/buildObjectType'
import Testimonials from './collections/Logos/Testimonials'
import ATS from './global/ATS'
app.get('/gatsby-schema-types', async (_, res) => {
interface IgatsbyNodeType {
gatsbyNodeType: string
fields: Field[]
}
const gatsbyNodeTypes: IgatsbyNodeType[] =[
{
gatsbyNodeType: "PayloadTestimonials",
fields: Testimonials.fields,
},
{
gatsbyNodeType: "PayloadAts",
fields: ATS.fields,
}
]
const schemas = gatsbyNodeTypes.map((node) => {
const query = buildObjectType({
payload,
name: node.gatsbyNodeType,
parentName: node.gatsbyNodeType,
fields: Testimonials.fields
})
const schema = new GraphQLSchema({query})
const sdl = printSchema(schema)
// Payload's JSON scalar conflicts with a built-in/Gatsby scalar
.replaceAll('JSON', 'PayloadJSON')
// replace backticks so we can paste the result into a string literal
.replaceAll('`', "\"")
// Gatsby won't load in the schema/query definition
.replace('schema {', '')
.replace(` query: ${node.gatsbyNodeType}`, '')
.replace('}', '')
return buildSchema(sdl)
})
const merged = mergeSchemas({
schemas
})
let report = printSchema(merged)
gatsbyNodeTypes.forEach(node => {
// Add Gatsby's Node interface to each type
report = report.replace(`type ${node.gatsbyNodeType} {`, `type ${node.gatsbyNodeType} implements Node {`)
})
res.setHeader('content-type', 'application/json')
res.send(report)
})
The generated SDL needs to be modified before use with Gatsby's createTypes
action.
TODO: Investigate an automated approach - are there any Gatsby/Payload/graphql classes/functions that can help?
implements Node
On each type that corresponds to a Gatsby Node type, implement the Node
interface.
type PayloadTestimonials implements Node
See https://www.gatsbyjs.com/docs/reference/graphql-data-layer/schema-customization/#the-node-interface.
schema {
query: PayloadTestimonial
}
If this is not removed, the following error is produced on gatsby develop
:
Missing onError handler for invocation 'building-schema', error was 'TypeError: Cannot read properties of undefined (reading 'value')'.
Stacktrace was 'TypeError: Cannot read properties of undefined (reading 'value')
The generated SDL include comments (wrapped in """
) that can use backticks - making it impossible to use a string literal. Replace with standard quotes or remove.
Missing onError handler for invocation 'building-schema', error was 'Invariant Violation: The GraphQL type `JSON` is reserved for internal use
by built-in scalar types.'. Stacktrace was 'Invariant Violation: The GraphQL type `JSON` is reserved for internal use by built-in scalar types.
References
Plugins that use GraphQL/schemas (other CMS implementations):