Skip to content

Commit

Permalink
apollographql#626 Integrate apollo-fastify plugin
Browse files Browse the repository at this point in the history
  • Loading branch information
addityasingh committed Apr 30, 2018
1 parent 1244ce9 commit 949d6d5
Show file tree
Hide file tree
Showing 15 changed files with 3,274 additions and 2 deletions.
5 changes: 4 additions & 1 deletion lerna.json
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,9 @@
}
},
"packages": [
"packages/*"
"packages/apollo-server-core",
"packages/apollo-server-integration-testsuite",
"packages/apollo-server-module-graphiql",
"packages/apollo-server-fastify"
]
}
1 change: 1 addition & 0 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@
"postinstall": "lerna bootstrap",
"pretest": "npm run compile",
"test": "npm run testonly --",
"tdd": "npm run compile && mocha --full-trace --timeout 5000 ./test/tests.js",
"posttest": "npm run lint",
"testonly": "mocha --reporter spec --full-trace --timeout 5000 ./test/tests.js",
"coverage": "istanbul cover -x \"*.test.js\" _mocha -- --timeout 5000 --full-trace --reporter dot ./test/tests.js",
Expand Down
6 changes: 6 additions & 0 deletions packages/apollo-server-fastify/.npmignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
*
!src/**/*
!dist/**/*
dist/**/*.test.*
!package.json
!README.md
40 changes: 40 additions & 0 deletions packages/apollo-server-fastify/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
---
title: Fastify
description: Setting up Apollo Server with Fastify
---

[![npm version](https://badge.fury.io/js/apollo-server-core.svg)](https://badge.fury.io/js/apollo-server-core) [![Build Status](https://circleci.com/gh/apollographql/apollo-cache-control-js.svg?style=svg)](https://circleci.com/gh/apollographql/apollo-cache-control-js) [![Coverage Status](https://coveralls.io/repos/github/apollographql/apollo-server/badge.svg?branch=master)](https://coveralls.io/github/apollographql/apollo-server?branch=master) [![Get on Slack](https://img.shields.io/badge/slack-join-orange.svg)](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
```

## Express

```js
import fastify from 'fastify';
import bodyParser from 'body-parser';
import { graphqlFastify } from 'apollo-server-fastify';

const myGraphQLSchema = // ... define or import your schema here!
const PORT = 3000;

const app = fastify();

// bodyParser is needed just for POST.
fastify.get('/graphql', bodyParser.json(), graphqlFastify({ schema: myGraphQLSchema }));

fastify.listen(PORT);
```

## 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!
42 changes: 42 additions & 0 deletions packages/apollo-server-fastify/package.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
{
"name": "apollo-server-fastify",
"version": "1.0.0",
"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"
}
}
70 changes: 70 additions & 0 deletions packages/apollo-server-fastify/src/fastifyApollo.test.ts
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);
});
});
136 changes: 136 additions & 0 deletions packages/apollo-server-fastify/src/fastifyApollo.ts
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;
}
5 changes: 5 additions & 0 deletions packages/apollo-server-fastify/src/index.ts
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';
9 changes: 9 additions & 0 deletions packages/apollo-server-fastify/tsconfig.json
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"]
}
1 change: 1 addition & 0 deletions packages/graphql-server-fastify/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
The `graphql-server-fastify` package is now called [`apollo-server-fastify`](https://www.npmjs.com/package/apollo-server-fastify). We are continuing to release matching versions of the package under the old name, but we recommend you switch to using the new name. The API is identical.
34 changes: 34 additions & 0 deletions packages/graphql-server-fastify/package.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
{
"name": "graphql-server-fastify",
"version": "1.0.0",
"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/graphql-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-fastify": "^1.0.0"
},
"typings": "dist/index.d.ts",
"typescript": {
"definition": "dist/index.d.ts"
}
}
1 change: 1 addition & 0 deletions packages/graphql-server-fastify/src/index.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
export * from 'apollo-server-fastify';
8 changes: 8 additions & 0 deletions packages/graphql-server-fastify/tsconfig.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
{
"extends": "../../tsconfig",
"compilerOptions": {
"rootDir": "./src",
"outDir": "./dist"
},
"exclude": ["node_modules", "dist"]
}
3 changes: 2 additions & 1 deletion test/tests.js
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,8 @@ require('../packages/apollo-server-express/dist/expressApollo.test');
require('../packages/apollo-server-express/dist/connectApollo.test');
(NODE_MAJOR_VERSION >= 9 ||
(NODE_MAJOR_VERSION >= 8 && NODE_MAJOR_REVISION >= 9)) &&
require('../packages/apollo-server-hapi/dist/hapiApollo.test'); // Hapi 17 is 8.9+
require('../packages/apollo-server-fastify/dist/fastifyApollo.test');
require('../packages/apollo-server-hapi/dist/hapiApollo.test'); // Hapi 17 is 8.9+
NODE_MAJOR_VERSION >= 6 &&
require('../packages/apollo-server-micro/dist/microApollo.test');
NODE_MAJOR_VERSION >= 7 &&
Expand Down
Loading

0 comments on commit 949d6d5

Please sign in to comment.