Skip to content

Commit a6ce6fb

Browse files
committed
feat: first setup of lambda handler
1 parent bf050c1 commit a6ce6fb

File tree

9 files changed

+188
-1
lines changed

9 files changed

+188
-1
lines changed

examples/lambda/.gitignore

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
# package directories
2+
node_modules
3+
jspm_packages
4+
5+
# Serverless directories
6+
.serverless

examples/lambda/handler.js

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,22 @@
1+
'use strict';
2+
import { GraphQLServerLambda } from 'graphql-yoga'
3+
4+
const typeDefs = `
5+
type Query {
6+
hello(name: String): String
7+
}
8+
`
9+
10+
const resolvers = {
11+
Query: {
12+
hello: (_,{ name }) => `Hello ${name}`
13+
}
14+
}
15+
16+
const server = new GraphQLServerLambda({
17+
typeDefs,
18+
resolvers
19+
})
20+
21+
exports.server = server.graphqlHandler
22+
exports.playground = server.playgroundHandler

examples/lambda/package.json

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
{
2+
"name": "lambda",
3+
"version": "1.0.0",
4+
"description": "",
5+
"main": "handler.js",
6+
"scripts": {
7+
"test": "echo \"Error: no test specified\" && exit 1"
8+
},
9+
"keywords": [],
10+
"author": "Kim Brandwijk <kim.brandwijk@gmail.com>",
11+
"license": "MIT",
12+
"dependencies": {
13+
"graphql-yoga": "*"
14+
}
15+
}

examples/lambda/serverless.yml

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
service: yoga-example
2+
3+
provider:
4+
name: aws
5+
runtime: nodejs6.10
6+
7+
functions:
8+
graphql:
9+
handler: handler.server
10+
events:
11+
- http:
12+
path: graphql
13+
method: post
14+
cors: true
15+
playground:
16+
handler: handler.playground
17+
events:
18+
- http:
19+
path: playground
20+
method: get
21+
cors: true

package.json

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -39,19 +39,22 @@
3939
"@types/zen-observable": "^0.5.3",
4040
"apollo-link": "^1.0.7",
4141
"apollo-server-express": "^1.3.2",
42+
"apollo-server-lambda": "1.3.2",
4243
"apollo-upload-server": "^4.0.0-alpha.1",
4344
"body-parser-graphql": "1.0.0",
4445
"cors": "^2.8.4",
4546
"express": "^4.16.2",
4647
"graphql": "^0.12.0",
4748
"graphql-import": "^0.2.0",
4849
"graphql-playground-middleware-express": "1.4.3",
50+
"graphql-playground-middleware-lambda": "1.3.6",
4951
"graphql-subscriptions": "^0.5.6",
5052
"graphql-tools": "^2.16.0",
5153
"portfinder": "^1.0.13",
5254
"subscriptions-transport-ws": "^0.9.4"
5355
},
5456
"devDependencies": {
57+
"@types/aws-lambda": "0.0.26",
5558
"tslint": "5.8.0",
5659
"tslint-config-standard": "7.0.0",
5760
"typescript": "2.6.2"

src/index.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,7 @@ export { PubSub, withFilter } from 'graphql-subscriptions'
1515
import { Props, Options } from './types'
1616

1717
export { Options }
18+
export { GraphQLServerLambda } from './lambda'
1819

1920
export class GraphQLServer {
2021
express: express.Application

src/lambda.ts

Lines changed: 88 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,88 @@
1+
import { graphqlLambda } from 'apollo-server-lambda'
2+
import * as fs from 'fs'
3+
import { GraphQLSchema } from 'graphql'
4+
import { importSchema } from 'graphql-import'
5+
import lambdaPlayground from 'graphql-playground-middleware-lambda'
6+
import { makeExecutableSchema } from 'graphql-tools'
7+
import * as path from 'path'
8+
9+
import { LambdaOptions, LambdaProps } from './types'
10+
11+
export class GraphQLServerLambda {
12+
options: LambdaOptions
13+
executableSchema: GraphQLSchema
14+
15+
// TODO: Get endpoint from a variable?
16+
playgroundHandler = lambdaPlayground({ endpoint: '/dev/graphql' })
17+
18+
protected context: any
19+
20+
constructor(props: LambdaProps) {
21+
const defaultOptions: LambdaOptions = {
22+
tracing: { mode: 'http-header' },
23+
}
24+
this.options = { ...defaultOptions, ...props.options }
25+
26+
this.context = props.context
27+
28+
if (props.schema) {
29+
this.executableSchema = props.schema
30+
} else if (props.typeDefs && props.resolvers) {
31+
let { typeDefs, resolvers } = props
32+
33+
// read from .graphql file if path provided
34+
if (typeDefs.endsWith('graphql')) {
35+
const schemaPath = path.isAbsolute(typeDefs) ? path.resolve(typeDefs) : path.resolve(typeDefs)
36+
37+
if (!fs.existsSync(schemaPath)) {
38+
throw new Error(`No schema found for path: ${schemaPath}`)
39+
}
40+
41+
typeDefs = importSchema(schemaPath)
42+
}
43+
44+
this.executableSchema = makeExecutableSchema({
45+
typeDefs,
46+
resolvers,
47+
})
48+
}
49+
}
50+
51+
graphqlHandler(event, context, callback) {
52+
function callbackFilter(error, output) {
53+
// eslint-disable-next-line no-param-reassign
54+
output.headers['Access-Control-Allow-Origin'] = '*'
55+
56+
callback(error, output)
57+
}
58+
59+
const tracing = event => {
60+
const t = this.options.tracing
61+
if (typeof t === 'boolean') {
62+
return t
63+
} else if (t.mode === 'http-header') {
64+
return event.headers['x-apollo-tracing'] !== undefined
65+
} else {
66+
return t.mode === 'enabled'
67+
}
68+
}
69+
70+
const handler = graphqlLambda(async (event, context) => {
71+
let apolloContext
72+
try {
73+
apolloContext =
74+
typeof this.context === 'function' ? await this.context({ event, context }) : this.context
75+
} catch (e) {
76+
console.error(e)
77+
throw e
78+
}
79+
80+
return {
81+
schema: this.executableSchema,
82+
tracing: tracing(event),
83+
context: apolloContext,
84+
}
85+
})
86+
return handler(event, context, callbackFilter)
87+
}
88+
}

src/types.ts

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -56,3 +56,16 @@ export interface Props {
5656
context?: Context | ContextCallback
5757
options?: Options
5858
}
59+
60+
export interface LambdaProps {
61+
typeDefs?: string
62+
resolvers?: IResolvers
63+
schema?: GraphQLSchema
64+
context?: Context | ContextCallback
65+
options?: LambdaOptions
66+
}
67+
68+
export interface LambdaOptions {
69+
tracing?: boolean | TracingOptions
70+
uploads?: UploadOptions
71+
}

yarn.lock

Lines changed: 19 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,10 @@
22
# yarn lockfile v1
33

44

5+
"@types/aws-lambda@0.0.26":
6+
version "0.0.26"
7+
resolved "https://registry.yarnpkg.com/@types/aws-lambda/-/aws-lambda-0.0.26.tgz#e16ae8ea87b63151cb48c6fba3c540282ff38902"
8+
59
"@types/body-parser@*":
610
version "1.16.8"
711
resolved "https://registry.yarnpkg.com/@types/body-parser/-/body-parser-1.16.8.tgz#687ec34140624a3bec2b1a8ea9268478ae8f3be3"
@@ -115,6 +119,13 @@ apollo-server-express@^1.3.2:
115119
apollo-server-core "^1.3.2"
116120
apollo-server-module-graphiql "^1.3.0"
117121

122+
apollo-server-lambda@1.3.2:
123+
version "1.3.2"
124+
resolved "https://registry.yarnpkg.com/apollo-server-lambda/-/apollo-server-lambda-1.3.2.tgz#bcf75f3d7115d11cc9892ad3b17427b3d536df0f"
125+
dependencies:
126+
apollo-server-core "^1.3.2"
127+
apollo-server-module-graphiql "^1.3.0"
128+
118129
apollo-server-module-graphiql@^1.3.0:
119130
version "1.3.0"
120131
resolved "https://registry.yarnpkg.com/apollo-server-module-graphiql/-/apollo-server-module-graphiql-1.3.0.tgz#077bb8c7bf292f6128c6c96d59c2096445b084ef"
@@ -564,7 +575,7 @@ graphql-import@^0.2.0:
564575
graphql "^0.12.3"
565576
lodash "^4.17.4"
566577

567-
graphql-playground-html@1.4.2:
578+
graphql-playground-html@1.4.2, graphql-playground-html@^1.3.6:
568579
version "1.4.2"
569580
resolved "https://registry.yarnpkg.com/graphql-playground-html/-/graphql-playground-html-1.4.2.tgz#af97a84ea6cf6ba18e8ff148a6a8b17eef40aa46"
570581
dependencies:
@@ -579,6 +590,13 @@ graphql-playground-middleware-express@1.4.3:
579590
graphql-playground-html "1.4.2"
580591
graphql-playground-middleware "^1.2.1-beta.6"
581592

593+
graphql-playground-middleware-lambda@1.3.6:
594+
version "1.3.6"
595+
resolved "https://registry.yarnpkg.com/graphql-playground-middleware-lambda/-/graphql-playground-middleware-lambda-1.3.6.tgz#eb7e2a03b180505b076d12592ed63623a9e0f880"
596+
dependencies:
597+
graphql-playground-html "^1.3.6"
598+
graphql-playground-middleware "^1.2.1-beta.6"
599+
582600
graphql-playground-middleware@^1.2.1-beta.6:
583601
version "1.2.1-beta.6"
584602
resolved "https://registry.yarnpkg.com/graphql-playground-middleware/-/graphql-playground-middleware-1.2.1-beta.6.tgz#b302bda88d28fae716d127a483659c8e70a18776"

0 commit comments

Comments
 (0)