From cd1c19d033bca1cf2d5806ca15bbb32890c3d5a3 Mon Sep 17 00:00:00 2001 From: Reyad Attiyat Date: Wed, 14 Dec 2016 14:51:56 -0600 Subject: [PATCH 01/17] Add support for AWS Lambda Create an integration that will return a lambda handler for a graphql or graphiql server. This integration requires an API Gateway with Lambda Proxy Integration. The test runner expects req and res objects for testing. We have to mock these for the tests to execute properly. --- packages/graphql-server-lambda/.npmignore | 5 + packages/graphql-server-lambda/README.md | 3 + packages/graphql-server-lambda/package.json | 43 +++++++ packages/graphql-server-lambda/src/index.ts | 6 + .../src/lambdaApollo.test.ts | 64 +++++++++++ .../graphql-server-lambda/src/lambdaApollo.ts | 106 ++++++++++++++++++ packages/graphql-server-lambda/tsconfig.json | 17 +++ test/tests.js | 1 + 8 files changed, 245 insertions(+) create mode 100755 packages/graphql-server-lambda/.npmignore create mode 100755 packages/graphql-server-lambda/README.md create mode 100644 packages/graphql-server-lambda/package.json create mode 100755 packages/graphql-server-lambda/src/index.ts create mode 100755 packages/graphql-server-lambda/src/lambdaApollo.test.ts create mode 100755 packages/graphql-server-lambda/src/lambdaApollo.ts create mode 100644 packages/graphql-server-lambda/tsconfig.json diff --git a/packages/graphql-server-lambda/.npmignore b/packages/graphql-server-lambda/.npmignore new file mode 100755 index 00000000000..063364e2b5d --- /dev/null +++ b/packages/graphql-server-lambda/.npmignore @@ -0,0 +1,5 @@ +* +!dist +!dist/**/* +dist/**/*.test.* +!package.json diff --git a/packages/graphql-server-lambda/README.md b/packages/graphql-server-lambda/README.md new file mode 100755 index 00000000000..ba4979c511b --- /dev/null +++ b/packages/graphql-server-lambda/README.md @@ -0,0 +1,3 @@ +# graphql-server-lambda + +This is the AWS Lambda integration for the Apollo community GraphQL Server. [Read the docs.](http://dev.apollodata.com/tools/apollo-server/index.html) diff --git a/packages/graphql-server-lambda/package.json b/packages/graphql-server-lambda/package.json new file mode 100644 index 00000000000..f5b8b9a87f1 --- /dev/null +++ b/packages/graphql-server-lambda/package.json @@ -0,0 +1,43 @@ +{ + "name": "graphql-server-lambda", + "version": "0.5.1", + "description": "Production-ready Node.js GraphQL server for AWS Lambda", + "main": "dist/index.js", + "scripts": { + "compile": "tsc", + "prepublish": "npm run compile" + }, + "repository": { + "type": "git", + "url": "https://github.com/apollostack/graphql-server/tree/master/packages/graphql-server-lambda" + }, + "keywords": [ + "GraphQL", + "Apollo", + "Server", + "Lambda", + "Javascript" + ], + "author": "Jonas Helfer ", + "license": "MIT", + "bugs": { + "url": "https://github.com/apollostack/graphql-server/issues" + }, + "homepage": "https://github.com/apollostack/graphql-server#readme", + "dependencies": { + "graphql-server-core": "^0.5.1", + "graphql-server-module-graphiql": "^0.4.4" + }, + "devDependencies": { + "@types/aws-lambda": "0.0.5", + "@types/graphql": "^0.8.6", + "graphql-server-integration-testsuite": "^0.5.1" + }, + "peerDependencies": { + "graphql": "^0.8.0 || ^0.9.0" + }, + "typings": "dist/index.d.ts", + "typescript": { + "definition": "dist/index.d.ts" + } +} diff --git a/packages/graphql-server-lambda/src/index.ts b/packages/graphql-server-lambda/src/index.ts new file mode 100755 index 00000000000..10f81ef3e46 --- /dev/null +++ b/packages/graphql-server-lambda/src/index.ts @@ -0,0 +1,6 @@ +export { + LambdaHandler, + IHeaders, + graphqlLambda, + graphiqlLambda +} from './lambdaApollo'; diff --git a/packages/graphql-server-lambda/src/lambdaApollo.test.ts b/packages/graphql-server-lambda/src/lambdaApollo.test.ts new file mode 100755 index 00000000000..f775d26d8f6 --- /dev/null +++ b/packages/graphql-server-lambda/src/lambdaApollo.test.ts @@ -0,0 +1,64 @@ +import { graphqlLambda, graphiqlLambda } from './lambdaApollo'; +import testSuite, { schema as Schema, CreateAppOptions } from 'graphql-server-integration-testsuite'; +import { expect } from 'chai'; +import { GraphQLOptions } from 'graphql-server-core'; +import 'mocha'; +import * as url from 'url'; + +function createLambda(options: CreateAppOptions = {}) { + let handler, + callback, + event, + context; + + options.graphqlOptions = options.graphqlOptions || { schema: Schema }; + if (options.graphiqlOptions ) { + handler = graphiqlLambda( options.graphiqlOptions ); + } else { + handler = graphqlLambda( options.graphqlOptions ); + } + + return function(req, res) { + let body = ''; + req.on('data', function (chunk) { + body += chunk; + }); + req.on('end', function() { + let urlObject = url.parse(req.url, true); + event = { + httpMethod: req.method, + body: body, + path: req.url, + queryStringParameters: urlObject.query, + }; + context = {}; + callback = function(error, result) { + res.statusCode = result.statusCode; + for (let key in result.headers) { + if (result.headers.hasOwnProperty(key)) { + res.setHeader(key, result.headers[key]); + } + } + res.write(result.body); + res.end(); + }; + + handler(event, context, callback); + }); + }; +} + +describe('lambdaApollo', () => { + it('throws error if called without schema', function(){ + expect(() => graphqlLambda(undefined as GraphQLOptions)).to.throw('Apollo Server requires options.'); + }); + + it('throws an error if called with more than one argument', function(){ + expect(() => (graphqlLambda)({}, {})).to.throw( + 'Apollo Server expects exactly one argument, got 2'); + }); +}); + +describe('integration:Lambda', () => { + testSuite(createLambda); +}); diff --git a/packages/graphql-server-lambda/src/lambdaApollo.ts b/packages/graphql-server-lambda/src/lambdaApollo.ts new file mode 100755 index 00000000000..21e4d012e55 --- /dev/null +++ b/packages/graphql-server-lambda/src/lambdaApollo.ts @@ -0,0 +1,106 @@ +import * as lambda from 'aws-lambda'; +import { GraphQLOptions, runHttpQuery } from 'graphql-server-core'; +import * as GraphiQL from 'graphql-server-module-graphiql'; + +export interface LambdaGraphQLOptionsFunction { + (event: any, context: lambda.Context): GraphQLOptions | Promise; +} + +// Design principles: +// - there is just one way allowed: POST request with JSON body. Nothing else. +// - simple, fast and secure +// + +export interface LambdaHandler { + (event: any, context: lambda.Context, callback: lambda.Callback): void; +} + +export interface IHeaders { + [header: string]: string | number; +} + +export function graphqlLambda( options: GraphQLOptions | LambdaGraphQLOptionsFunction ): LambdaHandler { + if (!options) { + throw new Error('Apollo Server requires options.'); + } + + if (arguments.length > 1) { + throw new Error(`Apollo Server expects exactly one argument, got ${arguments.length}`); + } + + return async (event, lambdaContext: lambda.Context, callback: lambda.Callback) => { + let query = (event.httpMethod === 'POST') ? event.body : event.queryStringParameters, + statusCode: number = null, + gqlResponse = null, + headers: {[headerName: string]: string} = {}; + + if (query && typeof query === 'string') { + query = JSON.parse(query); + } + + try { + gqlResponse = await runHttpQuery([event, lambdaContext], { + method: event.httpMethod, + options: options, + query: query, + }); + headers['Content-Type'] = 'application/json'; + statusCode = 200; + } catch (error) { + if ( 'HttpQueryError' !== error.name ) { + throw error; + } + + headers = error.headers; + statusCode = error.statusCode; + gqlResponse = error.message; + } finally { + callback( + null, + { + 'statusCode': statusCode, + 'headers': headers, + 'body': gqlResponse, + }, + ); + } + }; +} + +/* This Lambda Function Handler returns the html for the GraphiQL interactive query UI + * + * GraphiQLData arguments + * + * - endpointURL: the relative or absolute URL for the endpoint which GraphiQL will make queries to + * - (optional) query: the GraphQL query to pre-fill in the GraphiQL UI + * - (optional) variables: a JS object of variables to pre-fill in the GraphiQL UI + * - (optional) operationName: the operationName to pre-fill in the GraphiQL UI + * - (optional) result: the result of the query to pre-fill in the GraphiQL UI + */ + +export function graphiqlLambda(options: GraphiQL.GraphiQLData) { + return (event, lambdaContext: lambda.Context, callback: lambda.Callback) => { + const q = event.queryStringParameters || {}; + const query = q.query || ''; + const variables = q.variables || '{}'; + const operationName = q.operationName || ''; + + const graphiQLString = GraphiQL.renderGraphiQL({ + endpointURL: options.endpointURL, + query: query || options.query, + variables: q.variables && JSON.parse(variables) || options.variables, + operationName: operationName || options.operationName, + passHeader: options.passHeader, + }); + callback( + null, + { + 'statusCode': 200, + 'headers': { + 'Content-Type': 'text/html', + }, + 'body': graphiQLString, + }, + ); + }; +} diff --git a/packages/graphql-server-lambda/tsconfig.json b/packages/graphql-server-lambda/tsconfig.json new file mode 100644 index 00000000000..dcab1f88b17 --- /dev/null +++ b/packages/graphql-server-lambda/tsconfig.json @@ -0,0 +1,17 @@ +{ + "extends": "../../tsconfig", + "compilerOptions": { + "rootDir": "./src", + "outDir": "./dist", + "typeRoots": [ + "node_modules/@types" + ], + "types": [ + "@types/node" + ] + }, + "exclude": [ + "node_modules", + "dist" + ] +} diff --git a/test/tests.js b/test/tests.js index 4a9e10078b5..c1795c9d3bf 100644 --- a/test/tests.js +++ b/test/tests.js @@ -7,4 +7,5 @@ require('../packages/graphql-server-express/dist/connectApollo.test'); require('../packages/graphql-server-hapi/dist/hapiApollo.test'); require('../packages/graphql-server-koa/dist/koaApollo.test'); require('../packages/graphql-server-restify/dist/restifyApollo.test'); +require('../packages/graphql-server-lambda/dist/lambdaApollo.test'); require('../packages/graphql-server-express/dist/apolloServerHttp.test'); From 789a4ddf40c2342dbd1df903b735bac99998e1f9 Mon Sep 17 00:00:00 2001 From: Reyad Attiyat Date: Fri, 16 Dec 2016 23:41:32 -0600 Subject: [PATCH 02/17] Update README and Changelog Add example lambda handler and some documentation --- CHANGELOG.md | 2 ++ README.md | 15 ++++++++++++++- 2 files changed, 16 insertions(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index b10930969fd..bdc78413d3f 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -2,6 +2,8 @@ ### VNEXT +* Restify: Fix for calling next() (([@jadkap](https://github.com/jadkap)) on [#285](https://github.com/apollostack/graphql-server/pull/285)) +* Add AWS Lambda Integration [#101](https://github.com/apollostack/graphql-server/issues/101) * Restify: Fix for calling next() ([@jadkap](https://github.com/jadkap)) on [#285](https://github.com/apollostack/graphql-server/pull/285) * Update GraphiQL to version 0.9.1 ([@ephemer](https://github.com/ephemer)) on [#293](https://github.com/apollostack/graphql-server/pull/293) diff --git a/README.md b/README.md index 8e5be9d97e9..8affbe12f18 100644 --- a/README.md +++ b/README.md @@ -1,4 +1,4 @@ -# GraphQL Server for Express, Connect, Hapi, Koa, and Restify +# GraphQL Server for Express, Connect, Hapi, Koa, Restify and AWS Lambda [![npm version](https://badge.fury.io/js/graphql-server-core.svg)](https://badge.fury.io/js/graphql-server-core) [![Build Status](https://travis-ci.org/apollostack/graphql-server.svg?branch=master)](https://travis-ci.org/apollostack/graphql-server) @@ -31,6 +31,7 @@ where variant is one of the following: - express - koa - hapi + - lambda ### Express @@ -153,8 +154,20 @@ server.get('/graphiql', graphiqlRestify({ endpointURL: '/graphql' })); server.listen(PORT, () => console.log(`Listening on ${PORT}`)); ``` +### AWS Lambda + +Lambda function should be run with Node.js v4.3. Requires an API Gateway with Lambda Proxy Integration. + +```js +var server = require("graphql-server-lambda"); + +exports.handler = server.graphqlLambda({ schema: myGraphQLSchema }); +``` + ## Options +======= + GraphQL Server can be configured with an options object with the the following fields: * **schema**: the GraphQLSchema to be used From 2ff57f502e5db67ed2abbd0171b2abd74a57cb14 Mon Sep 17 00:00:00 2001 From: Reyad Attiyat Date: Wed, 25 Jan 2017 08:20:10 -0600 Subject: [PATCH 03/17] Add the restify variant to README --- README.md | 1 + 1 file changed, 1 insertion(+) diff --git a/README.md b/README.md index 8affbe12f18..c32212ec8d2 100644 --- a/README.md +++ b/README.md @@ -31,6 +31,7 @@ where variant is one of the following: - express - koa - hapi + - restify - lambda ### Express From 63bcd4696b7047eb7d14bd37e05aa0841a492b35 Mon Sep 17 00:00:00 2001 From: NeoReyad Date: Mon, 30 Jan 2017 23:54:24 -0600 Subject: [PATCH 04/17] Add instructions for deploying the Lambda Function This adds basic instructions to the README for deploying the lambda function. It uses the Serverless Application Model by creating a template that is used by the AWS CLI. --- packages/graphql-server-lambda/README.md | 82 ++++++++++++++++++++++++ 1 file changed, 82 insertions(+) diff --git a/packages/graphql-server-lambda/README.md b/packages/graphql-server-lambda/README.md index ba4979c511b..3be14106b3e 100755 --- a/packages/graphql-server-lambda/README.md +++ b/packages/graphql-server-lambda/README.md @@ -1,3 +1,85 @@ # graphql-server-lambda This is the AWS Lambda integration for the Apollo community GraphQL Server. [Read the docs.](http://dev.apollodata.com/tools/apollo-server/index.html) + +## How to Deploy +### AWS Serverless Application Model (SAM) + +To deploy the AWS Lambda function we must create a Cloudformation Template and a S3 bucket to store the artifact (zip of source code) and template. + +We will use the [AWS Command Line Interface](https://aws.amazon.com/cli/). + +#### Write the API handlers +graphql.js: +```javascript +var server = require("graphql-server-lambda"), + myGraphQLSchema = require("./schema"); + +exports.graphqlHandler = server.graphqlLambda({ schema: myGraphQLSchema }); +exports.graphiqlHandler = server.graphiqlLambda({ + endpointURL: '/Prod/graphql' +}); + +``` + +#### Create a S3 bucket + +The bucket name name must be universally unique. +``` +aws s3 mb s3:// +``` +#### Create the Template +This will look for a file called graphql.js with two exports: graphqlHandler and graphiqlHandler. It creates two API enpoints: +- /graphql (GET and POST) +- /graphiql (GET) + +template.yaml: +```yaml +AWSTemplateFormatVersion: '2010-09-09' +Transform: AWS::Serverless-2016-10-31 +Resources: + GraphQL: + Type: AWS::Serverless::Function + Properties: + Handler: graphql.graphqlHandler + Runtime: nodejs4.3 + Events: + GetRequest: + Type: Api + Properties: + Path: /graphql + Method: get + PostRequest: + Type: Api + Properties: + Path: /graphql + Method: post + GraphQLInspector: + Type: AWS::Serverless::Function + Properties: + Handler: graphql.graphiqlHandler + Runtime: nodejs4.3 + Events: + GetRequest: + Type: Api + Properties: + Path: /graphiql + Method: get + +``` +#### Pacakge source code and dependencies +This will read and transform the template, created in previous step. Package and upload the artifact to the S3 bucket and generate another template for the deployment. +``` +aws cloudformation package \ + --template-file template.yaml \ + --output-template-file serverless-output.yaml \ + --s3-bucket +``` +#### Deploy the API +The will create the Lambda Function and API Gateway for GraphQL. We use the stack-name prod to mean production but any stack name can be used. +``` +aws cloudformation deploy \ + --template-file serverless-output.yaml \ + --stack-name prod \ + --capabilities CAPABILITY_IAM +``` From ca00a96f1be5ec70db6e29c6fe5ccecbbc6313e1 Mon Sep 17 00:00:00 2001 From: Jonas Helfer Date: Mon, 30 Jan 2017 16:49:08 -0800 Subject: [PATCH 05/17] Update CONTRIBUTING.md --- CONTRIBUTING.md | 81 +++++++++++++++++++++++++++++++++++++++++++++++-- 1 file changed, 78 insertions(+), 3 deletions(-) diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index a8d38deb19d..15e894b88f0 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -1,10 +1,85 @@ -# Guidelines for contributors +# Apollo Contributor Guide -We're a very inclusive bunch here at Apollo, so anyone is welcome to contribute. Just fork the project, create a pull request and we'll work together to have it merged. +Excited about Apollo and want to make it better? We’re excited too! +Apollo is a community of developers just like you, striving to create the best tools and libraries around GraphQL. We welcome anyone who wants to contribute or provide constructive feedback, no matter the age or level of experience. If you want to help but don't know where to start, let us know, and we'll find something for you. -If you're unsure whether your pull request or feature is something that has a chance of being merged, just open an issue and ask away! +Oh, and if you haven't already, sign up for the [Apollo Slack](http://www.apollodata.com/#slack). +Here are some ways to contribute to the project, from easiest to most difficult: + +* [Reporting bugs](#reporting-bugs) +* [Improving the documentation](#improving-the-documentation) +* [Responding to issues](#responding-to-issues) +* [Small bug fixes](#small-bug-fixes) +* [Suggesting features](#suggesting-features) +* [Big pull requests](#big-prs) + +## Issues + +### Reporting bugs + +If you encounter a bug, please file an issue on GitHub via the repository of the sub-project you think contains the bug. If an issue you have is already reported, please add additional information or add a 👍 reaction to indicate your agreement. + +While we will try to be as helpful as we can on any issue reported, please include the following to maximize the chances of a quick fix: + +1. **Intended outcome:** What you were trying to accomplish when the bug occurred, and as much code as possible related to the source of the problem. +2. **Actual outcome:** A description of what actually happened, including a screenshot or copy-paste of any related error messages, logs, or other output that might be related. Places to look for information include your browser console, server console, and network logs. Please avoid non-specific phrases like “didn’t work” or “broke”. +3. **How to reproduce the issue:** Instructions for how the issue can be reproduced by a maintainer or contributor. Be as specific as possible, and only mention what is necessary to reproduce the bug. If possible, try to isolate the exact circumstances in which the bug occurs and avoid speculation over what the cause might be. + +Creating a good reproduction really helps contributors investigate and resolve your issue quickly. In many cases, the act of creating a minimal reproduction illuminates that the source of the bug was somewhere outside the library in question, saving time and effort for everyone. + +### Improving the documentation + +Improving the documentation, examples, and other open source content can be the easiest way to contribute to the library. If you see a piece of content that can be better, open a PR with an improvement, no matter how small! If you would like to suggest a big change or major rewrite, we’d love to hear your ideas but please open an issue for discussion before writing the PR. + +### Responding to issues + +In addition to reporting issues, a great way to contribute to Apollo is to respond to other peoples' issues and try to identify the problem or help them work around it. If you’re interested in taking a more active role in this process, please go ahead and respond to issues. And don't forget to say "Hi" on Apollo Slack! + +### Small bug fixes + +For a small bug fix change (less than 20 lines of code changed), feel free to open a pull request. We’ll try to merge it as fast as possible and ideally publish a new release on the same day. The only requirement is, make sure you also add a test that verifies the bug you are trying to fix. + +### Suggesting features + +Most of the features in Apollo came from suggestions by you, the community! We welcome any ideas about how to make Apollo better for your use case. Unless there is overwhelming demand for a feature, it might not get implemented immediately, but please include as much information as possible that will help people have a discussion about your proposal: + +1. **Use case:** What are you trying to accomplish, in specific terms? Often, there might already be a good way to do what you need and a new feature is unnecessary, but it’s hard to know without information about the specific use case. +2. **Could this be a plugin?** In many cases, a feature might be too niche to be included in the core of a library, and is better implemented as a companion package. If there isn’t a way to extend the library to do what you want, could we add additional plugin APIs? It’s important to make the case for why a feature should be part of the core functionality of the library. +3. **Is there a workaround?** Is this a more convenient way to do something that is already possible, or is there some blocker that makes a workaround unfeasible? + +Feature requests will be labeled as such, and we encourage using GitHub issues as a place to discuss new features and possible implementation designs. Please refrain from submitting a pull request to implement a proposed feature until there is consensus that it should be included. This way, you can avoid putting in work that can’t be merged in. + +Once there is a consensus on the need for a new feature, proceed as listed below under “Big PRs”. + +## Big PRs + +This includes: + +- Big bug fixes +- New features + +For significant changes to a repository, it’s important to settle on a design before starting on the implementation. This way, we can make sure that major improvements get the care and attention they deserve. Since big changes can be risky and might not always get merged, it’s good to reduce the amount of possible wasted effort by agreeing on an implementation design/plan first. + +1. **Open an issue.** Open an issue about your bug or feature, as described above. +2. **Reach consensus.** Some contributors and community members should reach an agreement that this feature or bug is important, and that someone should work on implementing or fixing it. +3. **Agree on intended behavior.** On the issue, reach an agreement about the desired behavior. In the case of a bug fix, it should be clear what it means for the bug to be fixed, and in the case of a feature, it should be clear what it will be like for developers to use the new feature. +4. **Agree on implementation plan.** Write a plan for how this feature or bug fix should be implemented. What modules need to be added or rewritten? Should this be one pull request or multiple incremental improvements? Who is going to do each part? +5. **Submit PR.** In the case where multiple dependent patches need to be made to implement the change, only submit one at a time. Otherwise, the others might get stale while the first is reviewed and merged. Make sure to avoid “while we’re here” type changes - if something isn’t relevant to the improvement at hand, it should be in a separate PR; this especially includes code style changes of unrelated code. +6. **Review.** At least one core contributor should sign off on the change before it’s merged. Look at the “code review” section below to learn about factors are important in the code review. If you want to expedite the code being merged, try to review your own code first! +7. **Merge and release!** + +### Code review guidelines + +It’s important that every piece of code in Apollo packages is reviewed by at least one core contributor familiar with that codebase. Here are some things we look for: + +1. **Required CI checks pass.** This is a prerequisite for the review, and it is the PR author's responsibility. As long as the tests don’t pass, the PR won't get reviewed. +2. **Simplicity.** Is this the simplest way to achieve the intended goal? If there are too many files, redundant functions, or complex lines of code, suggest a simpler way to do the same thing. In particular, avoid implementing an overly general solution when a simple, small, and pragmatic fix will do. +3. **Testing.** Do the tests ensure this code won’t break when other stuff changes around it? When it does break, will the tests added help us identify which part of the library has the problem? Did we cover an appropriate set of edge cases? Look at the test coverage report if there is one. Are all significant code paths in the new code exercised at least once? +4. **No unnecessary or unrelated changes.** PRs shouldn’t come with random formatting changes, especially in unrelated parts of the code. If there is some refactoring that needs to be done, it should be in a separate PR from a bug fix or feature, if possible. +5. **Code has appropriate comments.** Code should be commented, or written in a clear “self-documenting” way. +6. **Idiomatic use of the language.** In TypeScript, make sure the typings are specific and correct. In ES2015, make sure to use imports rather than require and const instead of var, etc. Ideally a linter enforces a lot of this, but use your common sense and follow the style of the surrounding code. ## New contributors From b3a00fffbcb087de20fba2276f6d844aefdfa7a4 Mon Sep 17 00:00:00 2001 From: Hagai Cohen Date: Sat, 4 Feb 2017 00:08:22 +0200 Subject: [PATCH 06/17] chore(package):fix badges in readme after org rename. --- README.md | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/README.md b/README.md index c32212ec8d2..8bf0d8c4eaa 100644 --- a/README.md +++ b/README.md @@ -1,9 +1,9 @@ # GraphQL Server for Express, Connect, Hapi, Koa, Restify and AWS Lambda [![npm version](https://badge.fury.io/js/graphql-server-core.svg)](https://badge.fury.io/js/graphql-server-core) -[![Build Status](https://travis-ci.org/apollostack/graphql-server.svg?branch=master)](https://travis-ci.org/apollostack/graphql-server) -[![Coverage Status](https://coveralls.io/repos/github/apollostack/graphql-server/badge.svg?branch=master)](https://coveralls.io/github/apollostack/graphql-server?branch=master) -[![Get on Slack](https://img.shields.io/badge/slack-join-orange.svg)](http://www.apollostack.com/#slack) +[![Build Status](https://travis-ci.org/apollographql/graphql-server.svg?branch=master)](https://travis-ci.org/apollographql/graphql-server) +[![Coverage Status](https://coveralls.io/repos/github/apollographql/graphql-server/badge.svg?branch=master)](https://coveralls.io/github/apollographql/graphql-server?branch=master) +[![Get on Slack](https://img.shields.io/badge/slack-join-orange.svg)](http://www.apollodata.com/#slack) GraphQL Server is a community-maintained open-source GraphQL server. It works with all Node.js HTTP server frameworks: Express, Connect, Hapi, Koa and Restify. From 9eab90d7d367fc61422262e6c3380a2eb1bd5d87 Mon Sep 17 00:00:00 2001 From: Rafael Cosman Date: Sat, 4 Feb 2017 00:12:58 -0800 Subject: [PATCH 07/17] Changes "apollo server" to "Graphql Server" --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index 8bf0d8c4eaa..a1a6fbbcf14 100644 --- a/README.md +++ b/README.md @@ -215,7 +215,7 @@ That said, GraphQL Server is heavily inspired by express-graphql (it's the refer ## GraphQL Server Development -If you want to develop apollo server locally you must follow the following instructions: +If you want to develop GraphQL Server locally you must follow the following instructions: * Fork this repository From 38e5932b3e66f7e30794664db701a315e22ee41d Mon Sep 17 00:00:00 2001 From: Hagai Cohen Date: Thu, 2 Feb 2017 02:47:12 +0200 Subject: [PATCH 08/17] chore(package): update lerna back to upstream package finally, lerna/lerna#507 fixed the devDep issue. --- lerna.json | 2 +- package.json | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/lerna.json b/lerna.json index eaf6bafd2c7..f943d643f23 100644 --- a/lerna.json +++ b/lerna.json @@ -1,5 +1,5 @@ { - "lerna": "2.0.0-beta.32", + "lerna": "2.0.0-beta.35", "version": "0.5.1", "changelog": { "repo": "apollostack/graphql-server", diff --git a/package.json b/package.json index d8fc19d4013..f7602876a7b 100644 --- a/package.json +++ b/package.json @@ -29,7 +29,7 @@ "chai": "^3.5.0", "graphql": "^0.9.0", "istanbul": "1.0.0-alpha.2", - "lerna": "git://github.com/DxCx/lerna.git#bootstrap-dev-bin-pkg", + "lerna": "2.0.0-beta.35", "mocha": "^3.2.0", "npm-check-updates": "^2.8.9", "remap-istanbul": "^0.8.4", From 8b9e4330259e0616db7b22f388fce0f465b1f45e Mon Sep 17 00:00:00 2001 From: Hagai Cohen Date: Thu, 2 Feb 2017 02:57:07 +0200 Subject: [PATCH 09/17] chore(package): update internal depenecies --- packages/graphql-server-express/package.json | 6 +++--- packages/graphql-server-hapi/package.json | 8 ++++---- .../graphql-server-integration-testsuite/package.json | 8 ++++---- packages/graphql-server-koa/package.json | 4 ++-- packages/graphql-server-lambda/package.json | 6 +++--- packages/graphql-server-restify/package.json | 4 ++-- 6 files changed, 18 insertions(+), 18 deletions(-) diff --git a/packages/graphql-server-express/package.json b/packages/graphql-server-express/package.json index 4042af875bc..9c93ec518c1 100644 --- a/packages/graphql-server-express/package.json +++ b/packages/graphql-server-express/package.json @@ -26,14 +26,14 @@ }, "homepage": "https://github.com/apollostack/graphql-server#readme", "dependencies": { - "graphql-server-core": "^0.5.1", - "graphql-server-module-graphiql": "^0.4.4" + "graphql-server-core": "^0.6.0", + "graphql-server-module-graphiql": "^0.6.0" }, "devDependencies": { "@types/body-parser": "0.0.33", "@types/connect": "^3.4.30", "@types/express": "^4.0.35", - "@types/multer": "0.0.32", + "@types/multer": "0.0.33", "body-parser": "^1.16.0", "connect": "^3.5.0", "connect-query": "^0.2.0", diff --git a/packages/graphql-server-hapi/package.json b/packages/graphql-server-hapi/package.json index 76abebb5a07..69e29497da6 100644 --- a/packages/graphql-server-hapi/package.json +++ b/packages/graphql-server-hapi/package.json @@ -25,13 +25,13 @@ }, "homepage": "https://github.com/apollostack/graphql-server#readme", "dependencies": { - "graphql-server-core": "^0.5.1", - "graphql-server-module-graphiql": "^0.4.4", + "graphql-server-core": "^0.6.0", + "graphql-server-module-graphiql": "^0.6.0", "boom": "^4.0.0" }, "devDependencies": { "@types/boom": "0.0.33", - "@types/hapi": "^13.0.35", + "@types/hapi": "^16.0.0", "graphql-server-integration-testsuite": "^0.5.1", "hapi": "^16.1.0", "@types/graphql": "^0.8.5" @@ -40,7 +40,7 @@ "graphql": "^0.8.0 || ^0.9.0" }, "optionalDependencies": { - "@types/hapi": "^13.0.35", + "@types/hapi": "^16.0.0", "@types/graphql": "^0.8.5" }, "typings": "dist/index.d.ts", diff --git a/packages/graphql-server-integration-testsuite/package.json b/packages/graphql-server-integration-testsuite/package.json index ad084af2be7..b8987968cb2 100644 --- a/packages/graphql-server-integration-testsuite/package.json +++ b/packages/graphql-server-integration-testsuite/package.json @@ -20,10 +20,10 @@ }, "homepage": "https://github.com/apollostack/graphql-server#readme", "dependencies": { - "graphql-server-core": "^0.5.1", - "graphql-server-module-graphiql": "^0.4.4", - "graphql-server-module-operation-store": "^0.5.0", - "supertest": "^2.0.0", + "graphql-server-core": "^0.6.0", + "graphql-server-module-graphiql": "^0.6.0", + "graphql-server-module-operation-store": "^0.6.0", + "supertest": "^3.0.0", "supertest-as-promised": "^4.0.0" }, "devDependencies": { diff --git a/packages/graphql-server-koa/package.json b/packages/graphql-server-koa/package.json index 0354256169b..084f7f0a667 100644 --- a/packages/graphql-server-koa/package.json +++ b/packages/graphql-server-koa/package.json @@ -25,8 +25,8 @@ }, "homepage": "https://github.com/apollostack/graphql-server#readme", "dependencies": { - "graphql-server-core": "^0.5.1", - "graphql-server-module-graphiql": "^0.4.4" + "graphql-server-core": "^0.6.0", + "graphql-server-module-graphiql": "^0.6.0" }, "devDependencies": { "@types/koa": "^2.0.33", diff --git a/packages/graphql-server-lambda/package.json b/packages/graphql-server-lambda/package.json index f5b8b9a87f1..69f32c8d565 100644 --- a/packages/graphql-server-lambda/package.json +++ b/packages/graphql-server-lambda/package.json @@ -25,11 +25,11 @@ }, "homepage": "https://github.com/apollostack/graphql-server#readme", "dependencies": { - "graphql-server-core": "^0.5.1", - "graphql-server-module-graphiql": "^0.4.4" + "graphql-server-core": "^0.6.0", + "graphql-server-module-graphiql": "^0.6.0" }, "devDependencies": { - "@types/aws-lambda": "0.0.5", + "@types/aws-lambda": "0.0.6", "@types/graphql": "^0.8.6", "graphql-server-integration-testsuite": "^0.5.1" }, diff --git a/packages/graphql-server-restify/package.json b/packages/graphql-server-restify/package.json index 2b3e5efc7f9..58a66e59a44 100644 --- a/packages/graphql-server-restify/package.json +++ b/packages/graphql-server-restify/package.json @@ -25,8 +25,8 @@ }, "homepage": "https://github.com/apollostack/graphql-server#readme", "dependencies": { - "graphql-server-core": "^0.5.1", - "graphql-server-module-graphiql": "^0.4.4" + "graphql-server-core": "^0.6.0", + "graphql-server-module-graphiql": "^0.6.0" }, "devDependencies": { "@types/restify": "^2.0.38", From e2c4258dbc0eda912fcf9a64146c7395331d3f8e Mon Sep 17 00:00:00 2001 From: Hagai Cohen Date: Fri, 3 Feb 2017 22:39:12 +0200 Subject: [PATCH 10/17] fix(tests): fixed typo in testcase of formatError --- packages/graphql-server-integration-testsuite/src/index.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/graphql-server-integration-testsuite/src/index.ts b/packages/graphql-server-integration-testsuite/src/index.ts index f48dc6c1cc7..9b7de3abb7f 100644 --- a/packages/graphql-server-integration-testsuite/src/index.ts +++ b/packages/graphql-server-integration-testsuite/src/index.ts @@ -639,7 +639,7 @@ export default (createApp: CreateAppFunc, destroyApp?: DestroyAppFunc) => { query: 'query test{ testError }', }); return req.then((res) => { - return expect(res.res.body.errors[0].message).to.equal('Internal server error'); + return expect(res.body.errors[0].message).to.equal('Internal server error'); }); }); From c4fabe367507f048f756ab4772942382449ef5a8 Mon Sep 17 00:00:00 2001 From: Urigo Date: Tue, 28 Feb 2017 20:05:45 +0200 Subject: [PATCH 11/17] added support for subscriptions --- .../src/expressApollo.ts | 1 + .../src/renderGraphiQL.ts | 84 +++++++++++++++---- 2 files changed, 67 insertions(+), 18 deletions(-) diff --git a/packages/graphql-server-express/src/expressApollo.ts b/packages/graphql-server-express/src/expressApollo.ts index d3ed376f9fd..b095a9f1405 100644 --- a/packages/graphql-server-express/src/expressApollo.ts +++ b/packages/graphql-server-express/src/expressApollo.ts @@ -72,6 +72,7 @@ export function graphiqlExpress(options: GraphiQL.GraphiQLData) { const graphiQLString = GraphiQL.renderGraphiQL({ endpointURL: options.endpointURL, + subscriptionsEndpoint: options.subscriptionsEndpoint, query: query || options.query, variables: q.variables && JSON.parse(q.variables) || options.variables, operationName: operationName || options.operationName, diff --git a/packages/graphql-server-module-graphiql/src/renderGraphiQL.ts b/packages/graphql-server-module-graphiql/src/renderGraphiQL.ts index 62ef287078e..2435e102998 100644 --- a/packages/graphql-server-module-graphiql/src/renderGraphiQL.ts +++ b/packages/graphql-server-module-graphiql/src/renderGraphiQL.ts @@ -66,6 +66,7 @@ export function renderGraphiQL(data: GraphiQLData): string { + `; From 68e4a35dc2e8308ab39b24447b3809dde72e3bfc Mon Sep 17 00:00:00 2001 From: Urigo Date: Thu, 9 Mar 2017 15:29:58 +0200 Subject: [PATCH 12/17] feat(subscriptions): added subscriptions for graphiql --- .../src/renderGraphiQL.ts | 68 ++++++------------- 1 file changed, 20 insertions(+), 48 deletions(-) diff --git a/packages/graphql-server-module-graphiql/src/renderGraphiQL.ts b/packages/graphql-server-module-graphiql/src/renderGraphiQL.ts index 2435e102998..dd806b4581c 100644 --- a/packages/graphql-server-module-graphiql/src/renderGraphiQL.ts +++ b/packages/graphql-server-module-graphiql/src/renderGraphiQL.ts @@ -20,6 +20,7 @@ export type GraphiQLData = { endpointURL: string, + subscriptionsEndpoint: string, query?: string, variables?: Object, operationName?: string, @@ -38,6 +39,7 @@ function safeSerialize(data) { export function renderGraphiQL(data: GraphiQLData): string { const endpointURL = data.endpointURL; + const subscriptionsEndpoint = data.subscriptionsEndpoint || ''; const queryString = data.query; const variablesString = data.variables ? JSON.stringify(data.variables, null, 2) : null; @@ -66,7 +68,7 @@ export function renderGraphiQL(data: GraphiQLData): string { - + `; From 54443b8bfebe764c59765d8c654e56da6c452c67 Mon Sep 17 00:00:00 2001 From: Urigo Date: Thu, 9 Mar 2017 15:51:22 +0200 Subject: [PATCH 13/17] feat(subscriptions): added subscriptions graphiql to all server types --- packages/graphql-server-hapi/src/hapiApollo.ts | 1 + packages/graphql-server-koa/src/koaApollo.ts | 1 + packages/graphql-server-lambda/src/lambdaApollo.ts | 1 + .../graphql-server-module-graphiql/src/renderGraphiQL.ts | 5 ----- packages/graphql-server-restify/src/restifyApollo.ts | 1 + 5 files changed, 4 insertions(+), 5 deletions(-) diff --git a/packages/graphql-server-hapi/src/hapiApollo.ts b/packages/graphql-server-hapi/src/hapiApollo.ts index 84cd4dc470e..4a5e7369bff 100644 --- a/packages/graphql-server-hapi/src/hapiApollo.ts +++ b/packages/graphql-server-hapi/src/hapiApollo.ts @@ -121,6 +121,7 @@ function renderGraphiQL(route, graphiqlParams: any, reply) { const graphiqlOptions = route.settings.plugins['graphiql']; const graphiQLString = GraphiQL.renderGraphiQL({ endpointURL: graphiqlOptions.endpointURL, + subscriptionsEndpoint: graphiqlOptions.subscriptionsEndpoint, query: graphiqlParams.query || graphiqlOptions.query, variables: graphiqlParams.variables && JSON.parse(graphiqlParams.variables) || graphiqlOptions.variables, operationName: graphiqlParams.operationName || graphiqlOptions.operationName, diff --git a/packages/graphql-server-koa/src/koaApollo.ts b/packages/graphql-server-koa/src/koaApollo.ts index 3bdeab0e901..ca19505c4d6 100644 --- a/packages/graphql-server-koa/src/koaApollo.ts +++ b/packages/graphql-server-koa/src/koaApollo.ts @@ -53,6 +53,7 @@ export function graphiqlKoa(options: GraphiQL.GraphiQLData) { const graphiQLString = GraphiQL.renderGraphiQL({ endpointURL: options.endpointURL, + subscriptionsEndpoint: options.subscriptionsEndpoint, query: query || options.query, variables: q.variables && JSON.parse(q.variables) || options.variables, operationName: operationName || options.operationName, diff --git a/packages/graphql-server-lambda/src/lambdaApollo.ts b/packages/graphql-server-lambda/src/lambdaApollo.ts index 21e4d012e55..a962edbd974 100755 --- a/packages/graphql-server-lambda/src/lambdaApollo.ts +++ b/packages/graphql-server-lambda/src/lambdaApollo.ts @@ -87,6 +87,7 @@ export function graphiqlLambda(options: GraphiQL.GraphiQLData) { const graphiQLString = GraphiQL.renderGraphiQL({ endpointURL: options.endpointURL, + subscriptionsEndpoint: options.subscriptionsEndpoint, query: query || options.query, variables: q.variables && JSON.parse(variables) || options.variables, operationName: operationName || options.operationName, diff --git a/packages/graphql-server-module-graphiql/src/renderGraphiQL.ts b/packages/graphql-server-module-graphiql/src/renderGraphiQL.ts index dd806b4581c..783193b2723 100644 --- a/packages/graphql-server-module-graphiql/src/renderGraphiQL.ts +++ b/packages/graphql-server-module-graphiql/src/renderGraphiQL.ts @@ -107,11 +107,6 @@ export function renderGraphiQL(data: GraphiQLData): string { var subscriptionsClient = new window.SubscriptionsTransportWs.SubscriptionClient('${subscriptionsEndpoint}', { reconnect: true }); - - subscriptionsClient.onConnect(function() { - console.log('Connected to GraphQL Subscriptions server...'); - }); - fetcher = window.SubscriptionsTransportWs.graphQLFetcher(subscriptionsClient, graphQLFetcher); } else { fetcher = graphQLFetcher; diff --git a/packages/graphql-server-restify/src/restifyApollo.ts b/packages/graphql-server-restify/src/restifyApollo.ts index 8fda0355b6a..44b72af42de 100644 --- a/packages/graphql-server-restify/src/restifyApollo.ts +++ b/packages/graphql-server-restify/src/restifyApollo.ts @@ -73,6 +73,7 @@ export function graphiqlRestify(options: GraphiQL.GraphiQLData) { const graphiQLString = GraphiQL.renderGraphiQL({ endpointURL: options.endpointURL, + subscriptionsEndpoint: options.subscriptionsEndpoint, query: query || options.query, variables: q.variables && JSON.parse(q.variables) || options.variables, operationName: operationName || options.operationName, From af86de8088cf49d0fd6a9fe04489f1fe7b8779e5 Mon Sep 17 00:00:00 2001 From: Urigo Date: Sat, 18 Mar 2017 21:59:06 +0200 Subject: [PATCH 14/17] feat(subscriptions): dont include transport if not using subscriptions --- .../graphql-server-module-graphiql/src/renderGraphiQL.ts | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/packages/graphql-server-module-graphiql/src/renderGraphiQL.ts b/packages/graphql-server-module-graphiql/src/renderGraphiQL.ts index 783193b2723..24027acf16a 100644 --- a/packages/graphql-server-module-graphiql/src/renderGraphiQL.ts +++ b/packages/graphql-server-module-graphiql/src/renderGraphiQL.ts @@ -39,7 +39,8 @@ function safeSerialize(data) { export function renderGraphiQL(data: GraphiQLData): string { const endpointURL = data.endpointURL; - const subscriptionsEndpoint = data.subscriptionsEndpoint || ''; + const subscriptionsEndpoint = data.subscriptionsEndpoint; + const usingSubscriptions = !!subscriptionsEndpoint; const queryString = data.query; const variablesString = data.variables ? JSON.stringify(data.variables, null, 2) : null; @@ -68,7 +69,7 @@ export function renderGraphiQL(data: GraphiQLData): string { - + ${usingSubscriptions ? '' : ''} - ${usingSubscriptions ? '' : ''} + ${usingSubscriptions ? + '' + + '' + : ''} ${usingSubscriptions ? '' + - '' + '' : ''} From 23b534a107bc6eff56527aaf32df00cbc059ee41 Mon Sep 17 00:00:00 2001 From: Urigo Date: Tue, 28 Mar 2017 20:29:12 +0300 Subject: [PATCH 17/17] feat(subscriptions): added missing "?" to props definition --- packages/graphql-server-module-graphiql/src/renderGraphiQL.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/graphql-server-module-graphiql/src/renderGraphiQL.ts b/packages/graphql-server-module-graphiql/src/renderGraphiQL.ts index 020ef094dcf..06ed2f64881 100644 --- a/packages/graphql-server-module-graphiql/src/renderGraphiQL.ts +++ b/packages/graphql-server-module-graphiql/src/renderGraphiQL.ts @@ -20,7 +20,7 @@ export type GraphiQLData = { endpointURL: string, - subscriptionsEndpoint: string, + subscriptionsEndpoint?: string, query?: string, variables?: Object, operationName?: string,