Skip to content

Instantly share code, notes, and snippets.

@iDVB
Last active October 20, 2021 20:13
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save iDVB/b009ecfbce5f40fed5d8ab09c808fd66 to your computer and use it in GitHub Desktop.
Save iDVB/b009ecfbce5f40fed5d8ab09c808fd66 to your computer and use it in GitHub Desktop.
Apollo Proxy for Remote Schema
import { Handler } from 'aws-lambda'
import { ApolloServer } from 'apollo-server-lambda'
import { makeExecutableSchema, mergeSchemas } from '@graphql-tools/schema'
import { introspectSchema, wrapSchema } from '@graphql-tools/wrap'
import { AsyncExecutor } from '@graphql-tools/utils'
import { fetch } from 'cross-fetch'
import { printSchema, print } from 'graphql'
const { CONTENTFUL_CDA, CONTENTFUL_SPACE } = process.env
const executor: AsyncExecutor = async ({ document, variables }) => {
const query = print(document)
const fetchResult = await fetch(
`https://graphql.contentful.com/content/v1/spaces/${CONTENTFUL_SPACE}`,
{
method: 'POST',
headers: {
'Content-Type': 'application/json',
Authorization: `Bearer ${CONTENTFUL_CDA}`,
},
body: JSON.stringify({ query, variables }),
},
)
return fetchResult.json()
}
const handler: Handler = async (event, context, callback) => {
// console.log({ event })
const role = event.requestContext?.authorizer?.role
console.log({ requestContext: event.requestContext, role })
const remoteSchema = wrapSchema({
schema: await introspectSchema(executor),
executor,
})
const localSchema = makeExecutableSchema({
typeDefs: printSchema(remoteSchema) + localExtensions,
resolvers: localResolvers,
})
const mergedSchema = mergeSchemas({
schemas: [remoteSchema, localSchema],
})
const server = new ApolloServer({
schema: mergedSchema,
context: {
role,
},
// introspection: true,
// plugins: [ApolloServerPluginLandingPageGraphQLPlayground()],
})
const createServer = server.createHandler()
return createServer(event, context, callback)
}
export const localExtensions = `
scalar _Any
scalar _FieldSet
type _Service {
sdl: String
}
extend type Query {
_service: _Service!
}
directive @external on FIELD_DEFINITION
directive @requires(fields: _FieldSet!) on FIELD_DEFINITION
directive @provides(fields: _FieldSet!) on FIELD_DEFINITION
directive @key(fields: _FieldSet!) repeatable on OBJECT | INTERFACE
# this is an optional directive discussed below
directive @extends on OBJECT | INTERFACE
extend type VideoPost {
url: String @requires(fields: "restrictToRoles")
}`
const localResolvers = {
VideoPost: {
url: (parent: any, args: any, context: any, info: any) => {
const isAllowed =
!parent.restrictToRoles?.length || parent.restrictToRoles?.includes(context.role)
console.log({ parent, args, context, info })
return isAllowed ? parent.url : null
},
},
}
export { handler }
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment