-
Notifications
You must be signed in to change notification settings - Fork 2k
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
feat(fastify): Integrate apollo-fastify plugin (#1013)
* Integrate apollo-fastify plugin #626 * #626 Fix typescript issues * #626 Update changelog * #626 Update README * #626 Fix the breaking tests * #626 Fix code review comments * #626 Run Hapi tests only for node 8 and 9 * #626 Run Hapi tests only for node 8 and 9 * #626 Commit package.lock in working state * #626 Use npm instead of yarn for node 4 * Revert package-lock and circle ci test job steps * #626 Bump the version
- Loading branch information
1 parent
d3aedd3
commit 8d5baec
Showing
10 changed files
with
350 additions
and
1 deletion.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,6 @@ | ||
* | ||
!src/**/* | ||
!dist/**/* | ||
dist/**/*.test.* | ||
!package.json | ||
!README.md |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,50 @@ | ||
--- | ||
title: Fastify | ||
description: Setting up Apollo Server with Fastify | ||
--- | ||
|
||
[](https://coveralls.io/github/apollographql/apollo-server?branch=master) [](https://www.apollographql.com/#slack) | ||
|
||
This is the Fastify integration of GraphQL Server. Apollo Server is a community-maintained open-source GraphQL server that works with all Node.js HTTP server frameworks: Express, Connect, Fastify, Hapi, Koa and Restify. [Read the docs](https://www.apollographql.com/docs/apollo-server/). [Read the CHANGELOG.](https://github.com/apollographql/apollo-server/blob/master/CHANGELOG.md) | ||
|
||
```sh | ||
npm install apollo-server-fastify | ||
``` | ||
|
||
## Fastify | ||
|
||
```js | ||
import fastify from 'fastify'; | ||
import jsonParser from 'fast-json-body'; | ||
import { graphqlFastify } from 'apollo-server-fastify'; | ||
|
||
const myGraphQLSchema = // ... define or import your schema here! | ||
const PORT = 3000; | ||
|
||
const app = fastify(); | ||
|
||
// jsonParser is needed for POST. | ||
app.addContentTypeParser('application/json', function(req, done) { | ||
jsonParser(req, function(err, body) { | ||
done(err, body); | ||
}); | ||
}); | ||
app.register(graphqlFastify, { schema: myGraphQLSchema }); | ||
|
||
try { | ||
await app.listen(3007); | ||
} catch (err) { | ||
app.log.error(err); | ||
process.exit(1); | ||
} | ||
``` | ||
|
||
## Principles | ||
|
||
GraphQL Server is built with the following principles in mind: | ||
|
||
* **By the community, for the community**: GraphQL Server's development is driven by the needs of developers | ||
* **Simplicity**: by keeping things simple, GraphQL Server is easier to use, easier to contribute to, and more secure | ||
* **Performance**: GraphQL Server is well-tested and production-ready - no modifications needed | ||
|
||
Anyone is welcome to contribute to GraphQL Server, just read [CONTRIBUTING.md](https://github.com/apollographql/apollo-server/blob/master/CONTRIBUTING.md), take a look at the [roadmap](https://github.com/apollographql/apollo-server/blob/master/ROADMAP.md) and make your first PR! |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,42 @@ | ||
{ | ||
"name": "apollo-server-fastify", | ||
"version": "1.0.4", | ||
"description": "Production-ready Node.js GraphQL server for fastify", | ||
"main": "dist/index.js", | ||
"scripts": { | ||
"compile": "tsc", | ||
"prepublish": "npm run compile" | ||
}, | ||
"repository": { | ||
"type": "git", | ||
"url": "https://github.com/apollographql/apollo-server/tree/master/packages/apollo-server-fastify" | ||
}, | ||
"keywords": [ | ||
"GraphQL", | ||
"Apollo", | ||
"Server", | ||
"Fastify", | ||
"Javascript" | ||
], | ||
"author": "Aditya pratap Singh <adisinghrajput@gmail.com>", | ||
"license": "MIT", | ||
"bugs": { | ||
"url": "https://github.com/apollographql/apollo-server/issues" | ||
}, | ||
"homepage": "https://github.com/apollographql/apollo-server#readme", | ||
"dependencies": { | ||
"apollo-server-core": "^1.3.6", | ||
"apollo-server-module-graphiql": "^1.3.4", | ||
"fastify": "1.3.1" | ||
}, | ||
"devDependencies": { | ||
"@types/graphql": "0.12.7", | ||
"apollo-server-integration-testsuite": "^1.3.6", | ||
"fast-json-body": "^1.1.0", | ||
"http2": "^3.3.7" | ||
}, | ||
"typings": "dist/index.d.ts", | ||
"typescript": { | ||
"definition": "dist/index.d.ts" | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,70 @@ | ||
import * as fastify from 'fastify'; | ||
import { FastifyInstance } from 'fastify'; | ||
const jsonParser = require('fast-json-body'); | ||
import { graphqlFastify, graphiqlFastify } from './fastifyApollo'; | ||
import testSuite, { | ||
schema, | ||
CreateAppOptions, | ||
} from 'apollo-server-integration-testsuite'; | ||
import { expect } from 'chai'; | ||
import { GraphQLOptions } from 'apollo-server-core'; | ||
import 'mocha'; | ||
|
||
async function createApp(options: CreateAppOptions = {}) { | ||
const app = fastify(); | ||
const graphqlOptions = options.graphqlOptions || { schema }; | ||
|
||
if (!options.excludeParser) { | ||
// @ts-ignore: Dynamic addContentTypeParser error | ||
app.addContentTypeParser('application/json', function(req, done) { | ||
jsonParser(req, function(err, body) { | ||
done(err, body); | ||
}); | ||
}); | ||
} | ||
|
||
if (options.graphiqlOptions) { | ||
app.register(graphiqlFastify, options.graphiqlOptions); | ||
} | ||
app.register(graphqlFastify, { graphqlOptions }); | ||
|
||
try { | ||
await app.listen(3007); | ||
} catch (err) { | ||
app.log.error(err); | ||
process.exit(1); | ||
} | ||
|
||
return app.server; | ||
} | ||
|
||
async function destroyApp(app) { | ||
if (!app || !app.close) { | ||
return; | ||
} | ||
await new Promise(cb => app.close(cb)); | ||
} | ||
|
||
describe('Fastify', () => { | ||
describe('fastifyApollo', () => { | ||
it('throws error if called without schema', function() { | ||
expect(() => | ||
graphqlFastify( | ||
{} as FastifyInstance, | ||
undefined as CreateAppOptions, | ||
undefined, | ||
), | ||
).to.throw('Apollo Server requires options.'); | ||
}); | ||
|
||
it('throws an error if called with argument not equal to 3', function() { | ||
expect(() => (<any>graphqlFastify)({}, { graphqlOptions: {} })).to.throw( | ||
'Apollo Server expects exactly 3 argument, got 2', | ||
); | ||
}); | ||
}); | ||
|
||
describe('integration:Fastify', () => { | ||
testSuite(createApp, destroyApp); | ||
}); | ||
}); |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,136 @@ | ||
import * as fastify from 'fastify'; | ||
import { | ||
runHttpQuery, | ||
HttpQueryRequest, | ||
GraphQLOptions, | ||
} from 'apollo-server-core'; | ||
import * as GraphiQL from 'apollo-server-module-graphiql'; | ||
import { | ||
FastifyInstance, | ||
FastifyRequest, | ||
FastifyReply, | ||
Middleware, | ||
} from 'fastify'; | ||
import { IncomingMessage, ServerResponse, Server } from 'http'; | ||
|
||
export function graphqlFastify( | ||
fastify: FastifyInstance, | ||
options: any, | ||
next: (err?: Error) => void, | ||
) { | ||
if (!options || !options.graphqlOptions) { | ||
throw new Error('Apollo Server requires options.'); | ||
} | ||
|
||
if (arguments.length !== 3) { | ||
throw new Error( | ||
`Apollo Server expects exactly 3 argument, got ${arguments.length}`, | ||
); | ||
} | ||
|
||
async function handler<HttpResponse extends ServerResponse>( | ||
request: any, | ||
reply: FastifyReply<HttpResponse>, | ||
) { | ||
const { method } = request.raw; | ||
try { | ||
const gqlResponse = await runHttpQuery([request], { | ||
method: method, | ||
options: options.graphqlOptions, | ||
query: method === 'POST' ? request.body : request.query, | ||
}); | ||
reply | ||
.type('application/json') | ||
.code(200) | ||
.header( | ||
'Content-Length', | ||
Buffer.byteLength(JSON.stringify(gqlResponse), 'utf8'), | ||
) | ||
.send(JSON.parse(gqlResponse)); | ||
} catch (error) { | ||
if ('HttpQueryError' !== error.name) { | ||
return next(error); | ||
} | ||
|
||
if (error.headers) { | ||
Object.keys(error.headers).forEach(header => { | ||
reply.header(header, error.headers[header]); | ||
}); | ||
} | ||
|
||
let errMessage; | ||
try { | ||
errMessage = JSON.parse(error.message); | ||
} catch { | ||
errMessage = error.message; | ||
} | ||
|
||
reply.code(error.statusCode).send(errMessage); | ||
} | ||
} | ||
|
||
fastify.route({ | ||
method: ['GET', 'POST'], | ||
url: options.url || '/graphql', | ||
handler, | ||
}); | ||
|
||
// This is a workaround because of this issue https://github.com/fastify/fastify/pull/862 | ||
fastify.route({ | ||
method: ['HEAD', 'PUT', 'DELETE', 'OPTIONS', 'PATCH'], | ||
url: options.url || '/graphql', | ||
handler: async (req, reply) => { | ||
reply | ||
.code(405) | ||
.header('allow', 'GET, POST') | ||
.send(); | ||
}, | ||
}); | ||
|
||
next(); | ||
return fastify; | ||
} | ||
|
||
export function graphiqlFastify( | ||
fastify: FastifyInstance, | ||
options: any, | ||
next: (err?: Error) => void, | ||
) { | ||
const handler = async (request, reply) => { | ||
try { | ||
const query = request.query; | ||
const giqlResponse = await GraphiQL.resolveGraphiQLString( | ||
query, | ||
options, | ||
request, | ||
); | ||
reply | ||
.header('Content-Type', 'text/html') | ||
.code(200) | ||
.send(giqlResponse); | ||
} catch (error) { | ||
reply.code(500).send(error); | ||
} | ||
}; | ||
|
||
fastify.route({ | ||
method: ['GET', 'POST'], | ||
url: options.url || '/graphiql', | ||
handler, | ||
}); | ||
|
||
// This is a workaround because of this issue https://github.com/fastify/fastify/pull/862 | ||
fastify.route({ | ||
method: ['HEAD', 'PUT', 'DELETE', 'OPTIONS', 'PATCH'], | ||
url: options.url || '/graphiql', | ||
handler: async (req, reply) => { | ||
reply | ||
.code(405) | ||
.header('allow', 'GET, POST') | ||
.send(); | ||
}, | ||
}); | ||
|
||
next(); | ||
return fastify; | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,5 @@ | ||
// Expose types which can be used by both middleware flavors. | ||
export { GraphQLOptions } from 'apollo-server-core'; | ||
|
||
// Fastify Middleware | ||
export { graphqlFastify, graphiqlFastify } from './fastifyApollo'; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,9 @@ | ||
{ | ||
"extends": "../../tsconfig", | ||
"compilerOptions": { | ||
"rootDir": "./src", | ||
"outDir": "./dist", | ||
"typeRoots": ["node_modules/@types"] | ||
}, | ||
"exclude": ["node_modules", "dist"] | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters