Working to set up a GatsbyJS plugin that sources from AWS AppSync using IAM auth. I keep getting an error that I can't track down what the problem is.
I don't have a ton of experience with graphql linking, and can't find good documentation on how to do it well in this context.
This is what my plugin gatsby-node.js file looks like:
const uuidv4 = require(`uuid/v4`)
const invariant = require(`invariant`)
const fetch = require(`node-fetch`)
const { createHttpLink } = require(`apollo-link-http`)
const { buildSchema, printSchema } = require(`graphql`)
const { makeRemoteExecutableSchema, transformSchema, introspectSchema, RenameTypes } = require(`graphql-tools`)
const AUTH_TYPE = require('aws-appsync/lib/link/auth-link').AUTH_TYPE
const AWS = require('aws-sdk');
const { createAppSyncLink } = require('aws-appsync');
exports.sourceNodes = async ( { actions, createNodeId, cache, createContentDigest }, options ) => {
const { createNode } = actions
delete options.plugins
const { typeName, fieldName, refetchInterval, HOST, PATH, REGION, AWS_ACCESS_KEY_ID, AWS_SECRET_ACCESS_KEY } = options
const url = HOST + PATH
// making sure things are required properly
invariant(
typeName && typeName.length > 0,
`gatsby-source-graphql requires option \`typeName\` to be specified`
)
invariant(
fieldName && fieldName.length > 0,
`gatsby-source-graphql requires option \`fieldName\` to be specified`
)
// Link to appsync
const fetcherLink = createHttpLink({
uri: url,
fetch: fetch
})
const type = AUTH_TYPE.AWS_IAM
AWS.config.update({
region: REGION,
credentials: new AWS.Credentials({
accessKeyId: AWS_ACCESS_KEY_ID,
secretAccessKey: AWS_SECRET_ACCESS_KEY
})
});
const credentials = AWS.config.credentials;
const link = createAppSyncLink({
url: url,
region: REGION,
auth: { type, credentials },
resultsFetcherLink: fetcherLink,
});
// Schema Creation
let introspectionSchema
const cacheKey = `gatsby-source-graphql-schema-${typeName}-${fieldName}`
let sdl = await cache.get(cacheKey)
console.log('sdl', sdl)
if (!sdl) {
introspectionSchema = await introspectSchema(link)
sdl = printSchema(introspectionSchema)
} else {
introspectionSchema = buildSchema(sdl)
}
await cache.set(cacheKey, sdl)
const remoteSchema = makeRemoteExecutableSchema({
schema: introspectionSchema,
link,
})
// Node creation
const nodeId = createNodeId(`gatsby-source-graphql-${typeName}`)
const node = createSchemaNode({
id: nodeId,
typeName,
fieldName,
createContentDigest,
})
createNode(node)
const resolver = (parent, args, context) => {
context.nodeModel.createPageDependency({
path: context.path,
nodeId: nodeId,
})
return {}
}
const schema = transformSchema(remoteSchema, [
new StripNonQueryTransform(),
new RenameTypes(name => `${typeName}_${name}`),
new NamespaceUnderFieldTransform({ typeName, fieldName, resolver }),
])
addThirdPartySchema({ schema })
if (process.env.NODE_ENV !== `production`) {
if (refetchInterval) {
const msRefetchInterval = refetchInterval * 1000
const refetcher = () => {
createNode(
createSchemaNode({
id: nodeId,
typeName,
fieldName,
createContentDigest,
})
)
setTimeout(refetcher, msRefetchInterval)
}
setTimeout(refetcher, msRefetchInterval)
}
}
}
function createSchemaNode({ id, typeName, fieldName, createContentDigest }) {
const nodeContent = uuidv4()
const nodeContentDigest = createContentDigest(nodeContent)
return {
id,
typeName: typeName,
fieldName: fieldName,
parent: null,
children: [],
internal: {
type: `GraphQLSource`,
contentDigest: nodeContentDigest,
ignoreType: true,
},
}
}
This is my error message:
TypeError: Cannot read property 'store' of undefined
client.js:147 [gatsby-source-appsync]/[aws-appsync]/lib/client.js:147:27
client.js:139 ApolloLink.request [gatsby-source-appsync]/[aws-appsync]/lib/client.js:139:23
bundle.umd.js:188 ApolloLink.request [gatsby-source-appsync]/[aws-appsync]/[apollo-link]/lib/bundle.umd.js:188:35
bundle.umd.js:188 ApolloLink.request [gatsby-source-appsync]/[aws-appsync]/[apollo-link]/lib/bundle.umd.js:188:35
bundle.umd.js:188 ApolloLink.request [gatsby-source-appsync]/[aws-appsync]/[apollo-link]/lib/bundle.umd.js:188:35
link.js:84 Object.execute [gatsby-source-appsync]/[apollo-link]/lib/link.js:84:18
linkToFetcher.js:7 [gatsby-source-appsync]/[graphql-tools]/dist/stitching/linkToFetcher.js:7:56
introspectSchema.js:50 [gatsby-source-appsync]/[graphql-tools]/dist/stitching/introspectSchema.js:50:42
introspectSchema.js:31 step [gatsby-source-appsync]/[graphql-tools]/dist/stitching/introspectSchema.js:31:23
introspectSchema.js:12 Object.next [gatsby-source-appsync]/[graphql-tools]/dist/stitching/introspectSchema.js:12:53
introspectSchema.js:6 [gatsby-source-appsync]/[graphql-tools]/dist/stitching/introspectSchema.js:6:71
new Promise
introspectSchema.js:2 __awaiter [gatsby-source-appsync]/[graphql-tools]/dist/stitching/introspectSchema.js:2:12
introspectSchema.js:41 introspectSchema [gatsby-source-appsync]/[graphql-tools]/dist/stitching/introspectSchema.js:41:12
gatsby-node.js:60 Object.exports.sourceNodes /workspace/plugins/gatsby-source-appsync/gatsby-node.js:60:33
Haven't worked much with graphql links before. Any help?
For your scenario, it might be better to use only the createAuthLink
from aws-appsync
, because createAppSyncLink
introduces a lot of stuff for offline scenarios that you don't seem to need (also, the full link for appsync depends on apollo's query manager inserting the cache in the operation context).
Something like this might work for you:
const { ApolloLink } = require(`apollo-link`)
const { createAuthLink } = require("aws-appsync");
const link = ApolloLink.from([
createAuthLink({
url: url,
region: REGION,
auth: { type, credentials },
}),
fetcherLink
]);