3

I was finally able to get TypeQL working with Netlify Functions / AWS Lambda after a day of work, going over the docs and examples, and in the end desperate brute force.

I'm sharing my working code here for others (or for future reference of my own :P ) as it contains some counterintuitive keyword usage.

Normal Approach

The error I kept getting when using the simple example was:

Your function response must have a numerical statusCode. You gave: $ undefined

I searched of course in the issues, but none of the suggested solutions worked for me.

Aerodynamic
  • 782
  • 5
  • 19

2 Answers2

2

Working Code

import 'reflect-metadata'
import { buildSchema } from 'type-graphql'
import { ApolloServer } from 'apollo-server-lambda'
import { RecipeResolver } from 'recipe-resolver'

async function lambdaFunction() {
  const schema = await buildSchema({
    resolvers: [RecipeResolver],
  })

  const server = new ApolloServer({
    schema,
    playground: true,
  })

  // !!! NOTE: return (await ) server.createHandler() won't work !
  exports.handler = server.createHandler()
}

// !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
// !!! NOTE: weird but only way to make it work with
// AWS lambda and netlify functions (netlify dev)
// also needs a reload of the page (first load of playground won't work)
lambdaFunction()
// exports.handler = lambdaFunction wont work
// export { lambdaFunction as handler } wont work
// !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!

Also I got some reflection errors from the simple example

Unable to infer GraphQL type from TypeScript reflection system. You need to provide explicit type for argument named 'title' of 'recipe' of 'RecipeResolver

So I had to figure out how to add explicit type to @Arg:

// previous:
// recipe(@Arg('title') title: string)
// fixed:
   recipe( @Arg('title', (type) => String) title: string
Dharman
  • 30,962
  • 25
  • 85
  • 135
Aerodynamic
  • 782
  • 5
  • 19
  • 1
    Thank you for sharing this. Did you find a way to explicitly add types to typegql objects? It's quite cumbersome to do this in an existing app with lots of objects. Maybe the decorators are not working? Not sure if netlify lambda is reading my tsconfig file – etudor May 26 '21 at 10:22
  • Maybe check the type-graphql issues. Apparently you need to redundantly define types (both on decorator as well as in class field) because of TS reflection system limitations. – Aerodynamic May 26 '21 at 16:37
  • @Aerodynamic did you ever end up serverless graphql this on a project? Was it dynamic pages/SSR, or just static pages? Wondering if you stayed with TypeGraphQL and Serverless and if the effort was worth it for the savings/scalability, or if you used a different provider/vendor/libs combo. – Jeffrey Gilbert Feb 25 '22 at 20:35
0

I share the code that works for me

// File: graphql.ts

import 'reflect-metadata'
import { buildSchema } from 'type-graphql'
import { ApolloServer } from 'apollo-server-lambda'
import { ApolloServerPluginLandingPageGraphQLPlayground } from 'apollo-server-core'
import { RecipeResolver } from './recipe-resolver'

export const createHandler = async function(){
  const schema = await buildSchema({
    resolvers: [RecipeResolver],
  })

  const server = new ApolloServer({
    schema,
    introspection: true,
    plugins: [ApolloServerPluginLandingPageGraphQLPlayground()],
  })

  return server.createHandler()
}

export const handler = async function(event, context, callback) {
  const graphqlHandler = await createHandler()
  return await graphqlHandler(event, context, callback)
}

// Lambda: graphql.handler
  • node16.x
  • type-graphql ^1.1.1
  • graphql ^15.3.0
  • apollo-server-lambda: ^3.10.2
Linh P
  • 1
  • 1