Reputation: 6745
When trying to generate types from Prismic with graphql-codegen I get the following error:
graphql/types.tsx
Failed to load schema from [object Object]:
invalid json response body at https://my-project-name.prismic.io/graphql reason: Unexpected t
oken < in JSON at position 0
It seems to be returning HTML I guess (hence the <
). If i go to the graphql url in Chrome I get the graphiql-editor. If I go to the url in Postman I get the missing query parameter
(which is expected) error, so the path seems to work in those environments. Is there a specific config I need to use with Prismic?
schema:
- https://my-project-name.prismic.io/graphql:
headers:
Prismic-Ref: PRISMIC_REF
documents:
- "graphql/**/*.ts"
generates:
graphql/types.tsx:
plugins:
- "typescript"
- "typescript-operations"
- "typescript-react-apollo"
config:
noHOC: true
noComponents: true
noNamespaces: true
withHooks: true
Upvotes: 0
Views: 1694
Reputation: 2634
There are a few elements to this:
GET
Prismic-ref
header must be passed with the ID of the master
refCodegen supports a customFetch
option which allows us to customise the outgoing request. I've packaged up the steps above into a customFetch
implementation and published it here:
https://www.npmjs.com/package/codegen-prismic-fetch
Upvotes: 1
Reputation: 11
This is indeed because the Prismic GraphQL api uses a GET instead of POST request. I actually did not find any tool which made it possible to introspect a GraphQL endpoint with a GET. After a little digging a came up with the following solution:
import {ApolloClient} from 'apollo-client'
import {InMemoryCache} from 'apollo-cache-inmemory'
import {HttpLink} from 'apollo-link-http'
import {setContext} from 'apollo-link-context'
import Prismic from 'prismic-javascript'
import fetch from 'isomorphic-unfetch'
const baseEndpoint = 'https://<your project>.cdn.prismic.io'
const accessToken = '<your access token>'
export default function createApolloClient(initialState, ctx) {
const primicClient = Prismic.client(`${baseEndpoint}/api`, {accessToken})
const prismicLink = setContext((req, options) => {
return primicClient.getApi().then(api => ({
headers: {
'Prismic-ref': api.masterRef.ref,
...options.headers,
...((api as any).integrationFieldRef
? {'Prismic-integration-field-ref': (api as any).integrationFieldRef}
: {}),
...(accessToken ? {Authorization: `Token ${accessToken}`} : {}),
},
}))
})
const httpLink = new HttpLink({
uri: `${baseEndpoint}/graphql`,
useGETForQueries: true,
fetch,
})
return new ApolloClient({
ssrMode: Boolean(ctx),
link: prismicLink.concat(httpLink),
cache: new InMemoryCache().restore(initialState),
})
}
import createApolloClient from '../apolloClient'
import gql from 'graphql-tag'
import path from 'path'
import fs from 'fs'
const client = createApolloClient({}, null)
const main = async () => {
try {
const res = await client.query({
query: gql`
query IntrospectionQuery {
__schema {
queryType {
name
}
mutationType {
name
}
subscriptionType {
name
}
types {
...FullType
}
directives {
name
description
locations
args {
...InputValue
}
}
}
}
fragment FullType on __Type {
kind
name
description
fields(includeDeprecated: true) {
name
description
args {
...InputValue
}
type {
...TypeRef
}
isDeprecated
deprecationReason
}
inputFields {
...InputValue
}
interfaces {
...TypeRef
}
enumValues(includeDeprecated: true) {
name
description
isDeprecated
deprecationReason
}
possibleTypes {
...TypeRef
}
}
fragment InputValue on __InputValue {
name
description
type {
...TypeRef
}
defaultValue
}
fragment TypeRef on __Type {
kind
name
ofType {
kind
name
ofType {
kind
name
ofType {
kind
name
ofType {
kind
name
ofType {
kind
name
ofType {
kind
name
ofType {
kind
name
}
}
}
}
}
}
}
}
`,
})
if (res.data) {
const schema = JSON.stringify(res.data)
// Specify where the schema should be written to
fs.writeFileSync(path.resolve(__dirname, '../../schema.json'), schema)
} else {
throw new Error('No Data')
}
process.exit()
} catch (e) {
console.log(e)
process.exit(1)
}
}
main()
codegen.yml
:schema: "./schema.json"
documents: ./src/**/*.graphql
generates:
./src/generated.tsx:
plugins:
- typescript
- typescript-operations
- typescript-react-apollo
config:
withHooks: true
withComponent: false
hooks:
afterStart:
- ts-node <path to script>/introspectPrismic.ts
Maybe it is not the most elegant solution but it works!
Upvotes: 1
Reputation: 31
I'm not very familiar with this tool but I guess that by default, this tool will try to make a call to the graphQL API with the POST Method. For Cache reasons, Prismic only uses GET for now so i'm pretty sure it has something to do with it. Hope it helps you figure it out.
Upvotes: 1