Remove packages for frameworks that don't yet support 2.0

Previously, we were planning to offer two kinds of APIs in "Apollo Server 2":
middleware functions just like in 1.0, and the new ApolloServer class.  We have
not yet implemented ApolloServer for all of our supported web frameworks, so
this meant that the 2.0 version of modules such as apollo-server-koa (which does
not yet have an ApolloServer class) offered very little benefits over
apollo-server-koa@1.0 (as most of the benefits of 2.0 come from ApolloServer).

This is confusing. We are going to improve the current registerServer API so
that there's no real benefit to using a separately-exported middleware directly
rather than creating an ApolloServer and applying it to your web framework. So
the AS 2.0 API will just be ApolloServer.  This means it doesn't make sense for
us to publish 2.x versions of the packages that don't yet support this API.

So this commit removes support for the following web frameworks: Adonis, Azure
Functions, Koa, Lambda, Micro, and Restify. (We leave in place Express, Hapi,
and Cloudflare workers.)

This isn't because we don't like these frameworks and don't want them to work
with Apollo Server 2.0!  We would love to see each package resurrected and an
ApolloServer implementation built, either during this current 2.x beta phase or
after the official 2.0 release. Deleting these packages for now makes it more
clear which frameworks support 2.0 and which don't, rather than existing in a
state where apollo-server-express@2 has ApolloServer and apollo-server-koa@2
does not.
This commit is contained in:
David Glasser 2018-06-13 13:45:10 -07:00
parent 1fd3b216d0
commit 40f9a4982f
46 changed files with 5 additions and 1969 deletions

View file

@ -1,11 +1,11 @@
# GraphQL Server for Express, Connect, Hapi, Koa, and more
Also supports: Restify, Micro, Azure Functions, AWS Lambda and Adonis Framework
# GraphQL Server for Express, Connect, Hapi, Cloudflare workers, and more
[![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)
[![Get on Slack](https://img.shields.io/badge/slack-join-orange.svg)](https://www.apollographql.com/#slack)
FIXME update README for 2.x; refer to 1.x branch for currently unsupported web frameworks and encourage community to help port ApolloServer to other frameworks.
Apollo Server is a community-maintained open-source GraphQL server. It works with pretty much all Node.js HTTP server frameworks, and we're happy to take PRs for more! Apollo Server works with any GraphQL schema built with [GraphQL.js](https://github.com/graphql/graphql-js), so you can build your schema with that directly or with a convenience library such as [graphql-tools](https://www.apollographql.com/docs/graphql-tools/).
## Documentation

View file

@ -1,6 +0,0 @@
*
!src/**/*
!dist/**/*
dist/**/*.test.*
!package.json
!README.md

View file

@ -1,78 +0,0 @@
---
title: Adonis
description: Setting up Apollo Server with Adonis
---
[![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 Adonis Framework integration of Apollo Server. Apollo Server is a community-maintained open-source Apollo Server that works with all Node.js HTTP server frameworks: Express, Connect, Hapi, Koa, Adonis Framework, 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-adonis
```
## Usage
```js
// start/routes.js
const { graphqlAdonis } = require('apollo-server-adonis');
// or using es6 modules
import { graphqlAdonis } from 'apollo-server-adonis';
const Route = use('Route');
Route.post('/graphql', graphqlAdonis({ schema: myGraphQLSchema }));
Route.get('/graphql', graphqlAdonis({ schema: myGraphQLSchema }));
```
### GraphiQL
You can also use `apollo-server-adonis` for hosting the [GraphiQL](https://github.com/graphql/graphiql) in-browser IDE. Note the difference between `graphqlAdonis` and `graphiqlAdonis`.
```js
// start/routes.js
const { graphiqlAdonis } = require('apollo-server-adonis');
// or using es6 modules
import { graphiqlAdonis } from 'apollo-server-adonis';
const Route = use('Route');
// Setup the /graphiql route to show the GraphiQL UI
Route.get(
'/graphiql',
graphiqlAdonis({
endpointURL: '/graphql', // a POST endpoint that GraphiQL will make the actual requests to
}),
);
```
In case your GraphQL endpoint is protected via authentication, or if you need to pass other custom headers in the request that GraphiQL makes, you can use the [`passHeader`](https://github.com/apollographql/apollo-server/blob/v1.0.2/packages/apollo-server-module-graphiql/src/renderGraphiQL.ts#L17) option  a string that will be added to the request header object.
For example:
```js
// start/routes.js
const { graphiqlAdonis } = require('apollo-server-adonis');
// or using es6 modules
import { graphiqlAdonis } from 'apollo-server-adonis';
const Route = use('Route');
Route.get(
'/graphiql',
graphiqlAdonis({
endpointURL: '/graphql',
passHeader: `'Authorization': 'Bearer lorem ipsum'`,
}),
);
```
## Principles
Apollo Server is built with the following principles in mind:
* **By the community, for the community**: Apollo Server's development is driven by the needs of developers
* **Simplicity**: by keeping things simple, Apollo Server is easier to use, easier to contribute to, and more secure
* **Performance**: Apollo Server is well-tested and production-ready - no modifications needed
Anyone is welcome to contribute to Apollo 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!

View file

@ -1,45 +0,0 @@
{
"name": "apollo-server-adonis",
"version": "2.0.0-beta.9",
"description": "Production-ready Node.js GraphQL server for Adonis Framework",
"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-adonis"
},
"keywords": [
"GraphQL",
"Apollo",
"Adonis",
"Server",
"Javascript"
],
"author": "Jonas Helfer <jonas@helfer.email>",
"license": "MIT",
"bugs": {
"url": "https://github.com/apollographql/apollo-server/issues"
},
"homepage": "https://github.com/apollographql/apollo-server#readme",
"engines": {
"node": ">=8"
},
"dependencies": {
"apollo-server-core": "^2.0.0-beta.9",
"apollo-server-module-graphiql": "^2.0.0-beta.8"
},
"devDependencies": {
"@adonisjs/bodyparser": "2.0.3",
"@adonisjs/fold": "4.0.8",
"@adonisjs/framework": "4.0.31",
"@adonisjs/sink": "1.0.16",
"apollo-server-integration-testsuite": "^2.0.0-beta.9"
},
"typings": "dist/index.d.ts",
"typescript": {
"definition": "dist/index.d.ts"
}
}

View file

@ -1,94 +0,0 @@
// tslint:disable: variable-name no-var-requires
import { ioc, registrar } from '@adonisjs/fold';
import { setupResolver, Config } from '@adonisjs/sink';
import { graphqlAdonis, graphiqlAdonis } from './adonisApollo';
import { GraphQLOptions } from 'apollo-server-core';
import { expect } from 'chai';
import testSuite, {
schema,
CreateAppOptions,
} from 'apollo-server-integration-testsuite';
const RouteStore = require('@adonisjs/framework/src/Route/Store');
async function createApp(options: CreateAppOptions = {}) {
ioc.restore();
RouteStore.clear();
options.graphqlOptions = options.graphqlOptions || { schema };
const providers = ['@adonisjs/framework/providers/AppProvider'];
if (!options.excludeParser) {
providers.push('@adonisjs/bodyparser/providers/BodyParserProvider');
}
setupResolver();
registrar.providers(providers).register();
ioc.bind('Adonis/Src/Config', () => {
const config = new Config();
config.set('app', {
logger: {
transport: 'console',
console: {
driver: 'console',
},
},
});
return config;
});
const Context = ioc.use('Adonis/Src/HttpContext');
const Request = ioc.use('Adonis/Src/Request');
const Response = ioc.use('Adonis/Src/Response');
const Route = ioc.use('Adonis/Src/Route');
const Server = ioc.use('Adonis/Src/Server');
Context.getter(
'request',
function() {
return new Request(this.req, this.res, ioc.use('Adonis/Src/Config'));
},
true,
);
Context.getter(
'response',
function() {
return new Response(this.req, this.res, ioc.use('Adonis/Src/Config'));
},
true,
);
Route.post('/graphql', graphqlAdonis(options.graphqlOptions));
Route.get('/graphql', graphqlAdonis(options.graphqlOptions));
if (options.graphiqlOptions) {
Route.get('/graphiql', graphiqlAdonis(options.graphiqlOptions));
}
if (!options.excludeParser) {
Server.registerGlobal(['Adonis/Middleware/BodyParser']);
}
await new Promise(resolve => Server.listen('localhost', 3333, resolve));
return Server.getInstance();
}
async function destroyApp(app) {
if (!app || !app.close) {
return;
}
await new Promise(resolve => app.close(resolve));
}
describe('adonisApollo', () => {
it('throws error if called without schema', function() {
expect(() => graphqlAdonis(undefined as GraphQLOptions)).to.throw(
'Apollo Server requires options.',
);
});
it('throws an error if called with more than one argument', function() {
expect(() => (<any>graphqlAdonis)({}, 'x')).to.throw(
'Apollo Server expects exactly one argument, got 2',
);
});
});
describe('integration:Adonis', () => {
testSuite(createApp, destroyApp);
});

View file

@ -1,82 +0,0 @@
import AdonisContext from '@adonisjs/framework/src/Context';
import {
GraphQLOptions,
HttpQueryError,
runHttpQuery,
convertNodeHttpToRequest,
} from 'apollo-server-core';
import * as GraphiQL from 'apollo-server-module-graphiql';
export interface AdonisGraphQLOptionsFunction {
(ctx: AdonisContext): GraphQLOptions | Promise<GraphQLOptions>;
}
export interface AdonisHandler {
(req: any, next): void;
}
export function graphqlAdonis(
options: GraphQLOptions | AdonisGraphQLOptionsFunction,
): AdonisHandler {
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}`,
);
}
const graphqlHandler = (ctx: AdonisContext): Promise<void> => {
const { request, response } = ctx;
const method = request.method();
const query = method === 'POST' ? request.post() : request.get();
return runHttpQuery([ctx], {
method,
options,
query,
request: convertNodeHttpToRequest(request.request),
}).then(
gqlResponse => {
response.type('application/json');
response.json(gqlResponse);
},
(error: HttpQueryError) => {
if ('HttpQueryError' !== error.name) {
throw error;
}
if (error.headers) {
Object.keys(error.headers).forEach(header => {
response.header(header, error.headers[header]);
});
}
response.status(error.statusCode).send(error.message);
},
);
};
return graphqlHandler;
}
export interface AdonisGraphiQLOptionsFunction {
(ctx: AdonisContext): GraphiQL.GraphiQLData | Promise<GraphiQL.GraphiQLData>;
}
export function graphiqlAdonis(
options: GraphiQL.GraphiQLData | AdonisGraphiQLOptionsFunction,
) {
const graphiqlHandler = (ctx: AdonisContext): Promise<void> => {
const { request, response } = ctx;
const query = request.get();
return GraphiQL.resolveGraphiQLString(query, options, ctx).then(
graphiqlString => {
response.type('text/html').send(graphiqlString);
},
(error: HttpQueryError) => {
response.status(500).send(error.message);
},
);
};
return graphiqlHandler;
}

View file

@ -1,7 +0,0 @@
export {
AdonisGraphQLOptionsFunction,
AdonisHandler,
AdonisGraphiQLOptionsFunction,
graphqlAdonis,
graphiqlAdonis,
} from './adonisApollo';

View file

@ -1,8 +0,0 @@
{
"extends": "../../tsconfig",
"compilerOptions": {
"rootDir": "./src",
"outDir": "./dist"
},
"exclude": ["node_modules", "dist"]
}

View file

@ -1,6 +0,0 @@
*
!dist
!dist/**/*
dist/**/*.test.*
!package.json
!README.md

View file

@ -1,70 +0,0 @@
---
title: Azure Functions
description: Setting up Apollo Server with Azure Functions
---
[![npm version](https://badge.fury.io/js/apollo-server-core.svg)](https://badge.fury.io/js/apollo-server-core) [![Build Status](https://travis-ci.org/apollographql/apollo-server.svg?branch=master)](https://travis-ci.org/apollographql/apollo-server) [![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 Azure Functions integration for the Apollo community GraphQL Server. [Read the docs.](https://www.apollographql.com/docs/apollo-server/)
## Sample Code
### GraphQL:
```javascript
const { graphqlAzureFunctions } = require('apollo-server-azure-functions');
const { makeExecutableSchema } = require('graphql-tools');
const typeDefs = `
type Random {
id: Int!
rand: String
}
type Query {
rands: [Random]
rand(id: Int!): Random
}
`;
const rands = [{ id: 1, rand: 'random' }, { id: 2, rand: 'modnar' }];
const resolvers = {
Query: {
rands: () => rands,
rand: (_, { id }) => rands.find(rand => rand.id === id),
},
};
const schema = makeExecutableSchema({
typeDefs,
resolvers,
});
module.exports = function run(context, request) {
graphqlAzureFunctions({ schema })(context, request);
};
```
### GraphiQL
```javascript
const { graphiqlAzureFunctions } = require('apollo-server-azure-functions');
export function run(context, request) {
let query = `
{
rands {
id
rand
}
}
`;
// End point points to the path to the GraphQL API function
graphiqlAzureFunctions({ endpointURL: '/api/graphql', query })(
context,
request,
);
}
```

View file

@ -1,42 +0,0 @@
{
"name": "apollo-server-azure-functions",
"version": "2.0.0-beta.9",
"description": "Node.js GraphQl server for Azure Functions",
"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-azure-functions"
},
"keywords": [
"GraphQL",
"Apollo",
"Server",
"Azure",
"Functions"
],
"author": "Ulrik Strid <ulrik.strid@outlook.com>",
"license": "MIT",
"bugs": {
"url": "https://github.com/apollographql/apollo-server/issues"
},
"homepage": "https://github.com/apollographql/apollo-server#readme",
"engines": {
"node": ">=8"
},
"dependencies": {
"apollo-server-core": "^2.0.0-beta.9",
"apollo-server-module-graphiql": "^2.0.0-beta.8"
},
"devDependencies": {
"apollo-server-integration-testsuite": "^2.0.0-beta.9",
"azure-functions-typescript": "0.0.1"
},
"typings": "dist/index.d.ts",
"typescript": {
"definition": "dist/index.d.ts"
}
}

View file

@ -1,89 +0,0 @@
import {
AzureFunctionsHandler,
graphqlAzureFunctions,
graphiqlAzureFunctions,
} from './azureFunctionsApollo';
import testSuite, {
schema as Schema,
CreateAppOptions,
} from 'apollo-server-integration-testsuite';
import { expect } from 'chai';
import { GraphQLOptions } from 'apollo-server-core';
import 'mocha';
import url from 'url';
function createFunction(options: CreateAppOptions = {}) {
let route, context;
let handler: AzureFunctionsHandler;
options.graphqlOptions = options.graphqlOptions || { schema: Schema };
if (options.graphiqlOptions) {
route = '/graphiql';
handler = graphiqlAzureFunctions(options.graphiqlOptions);
} else {
route = '/graphql';
handler = graphqlAzureFunctions(options.graphqlOptions);
}
return function(req, res) {
if (!req.url.startsWith(route)) {
res.statusCode = 404;
res.end();
return;
}
let body = '';
req.on('data', function(chunk) {
body += chunk;
});
req.on('end', function() {
let urlObject = url.parse(req.url, true);
const request = {
method: req.method,
originalUrl: req.url,
query: urlObject.query,
headers: req.headers,
body: body,
rawbody: body,
};
context = {
done: function(error, result) {
res.statusCode = result.status;
for (let key in result.headers) {
if (result.headers.hasOwnProperty(key)) {
res.setHeader(key, result.headers[key]);
}
}
if (error) {
res.error = error;
}
res.write(result.body);
res.end();
},
};
handler(context, request as any);
});
};
}
describe('azureFunctionsApollo', () => {
it('throws error if called without schema', function() {
expect(() => graphqlAzureFunctions(undefined as GraphQLOptions)).to.throw(
'Apollo Server requires options.',
);
});
it('throws an error if called with more than one argument', function() {
expect(() => (<any>graphqlAzureFunctions)({}, {})).to.throw(
'Apollo Server expects exactly one argument, got 2',
);
});
});
describe('integration:Azure Functions', () => {
testSuite(createFunction);
});

View file

@ -1,141 +0,0 @@
import {
HttpContext,
IFunctionRequest,
HttpStatusCodes,
} from 'azure-functions-typescript';
import { GraphQLOptions, runHttpQuery } from 'apollo-server-core';
import {
GraphiQLData,
resolveGraphiQLString,
} from 'apollo-server-module-graphiql';
export interface AzureFunctionsGraphQLOptionsFunction {
(context: HttpContext): GraphQLOptions | Promise<GraphQLOptions>;
}
export interface AzureFunctionsHandler {
(context: HttpContext, request: IFunctionRequest): void;
}
export interface IHeaders {
'content-type'?: string;
'content-length'?: HttpStatusCodes | number;
'content-disposition'?: string;
'content-encoding'?: string;
'content-language'?: string;
'content-range'?: string;
'content-location'?: string;
'content-md5'?: Buffer;
expires?: Date;
'last-modified'?: Date;
[header: string]: any;
}
export interface AzureFunctionsGraphiQLOptionsFunction {
(context: HttpContext, request: IFunctionRequest):
| GraphiQLData
| Promise<GraphiQLData>;
}
export function graphqlAzureFunctions(
options: GraphQLOptions | AzureFunctionsGraphQLOptionsFunction,
): AzureFunctionsHandler {
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}`,
);
}
const graphqlHandler = (
httpContext: HttpContext,
request: IFunctionRequest,
) => {
const queryRequest = {
method: request.method,
options: options,
query: request.method === 'POST' ? request.body : request.query,
request,
};
if (queryRequest.query && typeof queryRequest.query === 'string') {
queryRequest.query = JSON.parse(queryRequest.query);
}
return runHttpQuery([httpContext, request], queryRequest as any)
.then(gqlResponse => {
const result = {
status: HttpStatusCodes.OK,
headers: {
'Content-Type': 'application/json',
},
body: gqlResponse,
isRaw: true,
};
httpContext.res = result;
httpContext.done(null, result);
})
.catch(error => {
const result = {
status: error.statusCode,
headers: error.headers,
body: error.message,
};
httpContext.res = result;
httpContext.done(null, result);
});
};
return graphqlHandler;
}
/* This Azure Functions 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 graphiqlAzureFunctions(
options: GraphiQLData | AzureFunctionsGraphiQLOptionsFunction,
) {
const graphiqlHandler = (
httpContext: HttpContext,
request: IFunctionRequest,
) => {
const query = request.query;
resolveGraphiQLString(query, options, httpContext, request).then(
graphiqlString => {
const result = {
status: HttpStatusCodes.OK,
headers: {
'Content-Type': 'text/html',
},
body: graphiqlString,
isRaw: true,
};
httpContext.res = result;
httpContext.done(null, result);
},
error => {
httpContext.res = {
status: 500,
body: error.message,
};
httpContext.done(null, httpContext.res);
},
);
};
return graphiqlHandler;
}

View file

@ -1,8 +0,0 @@
export {
AzureFunctionsHandler,
IHeaders,
AzureFunctionsGraphQLOptionsFunction,
AzureFunctionsGraphiQLOptionsFunction,
graphqlAzureFunctions,
graphiqlAzureFunctions,
} from './azureFunctionsApollo';

View file

@ -1,8 +0,0 @@
{
"extends": "../../tsconfig",
"compilerOptions": {
"rootDir": "./src",
"outDir": "./dist"
},
"exclude": ["node_modules", "dist"]
}

View file

@ -5,7 +5,7 @@ description: Setting up Apollo Server with Express.js or Connect
[![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 Express and Connect 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, 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)
This is the Express and Connect integration of GraphQL Server. Apollo Server is a community-maintained open-source GraphQL server that works with many Node.js HTTP server frameworks. [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@beta apollo-server-express@beta

View file

@ -5,7 +5,7 @@ description: Setting up Apollo Server with Hapi
[![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 Hapi integration of Apollo Server. Apollo Server is a community-maintained open-source Apollo Server that works with all Node.js HTTP server frameworks: Express, Connect, 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)
This is the Hapi integration of Apollo Server. Apollo Server is a community-maintained open-source Apollo Server that works with many Node.js HTTP server frameworks. [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-hapi@beta

View file

@ -1,6 +0,0 @@
*
!src/**/*
!dist/**/*
dist/**/*.test.*
!package.json
!README.md

View file

@ -1,77 +0,0 @@
---
title: Koa
description: Setting up Apollo Server with Koa
---
[![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 Koa integration of Apollo Server. Apollo Server is a community-maintained open-source Apollo Server that works with all Node.js HTTP server frameworks: Express, Connect, 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-koa
```
## Usage
```js
import koa from 'koa'; // koa@2
import koaRouter from 'koa-router';
import koaBody from 'koa-bodyparser';
import { graphqlKoa } from 'apollo-server-koa';
const app = new koa();
const router = new koaRouter();
const PORT = 3000;
// koaBody is needed just for POST.
app.use(koaBody());
router.post('/graphql', graphqlKoa({ schema: myGraphQLSchema }));
router.get('/graphql', graphqlKoa({ schema: myGraphQLSchema }));
app.use(router.routes());
app.use(router.allowedMethods());
app.listen(PORT);
```
### GraphiQL
You can also use `apollo-server-koa` for hosting the [GraphiQL](https://github.com/graphql/graphiql) in-browser IDE. Note the difference between `graphqlKoa` and `graphiqlKoa`.
```js
import { graphiqlKoa } from 'apollo-server-koa';
// Setup the /graphiql route to show the GraphiQL UI
router.get(
'/graphiql',
graphiqlKoa({
endpointURL: '/graphql', // a POST endpoint that GraphiQL will make the actual requests to
}),
);
```
In case your GraphQL endpoint is protected via authentication, or if you need to pass other custom headers in the request that GraphiQL makes, you can use the [`passHeader`](https://github.com/apollographql/apollo-server/blob/v1.0.2/packages/apollo-server-module-graphiql/src/renderGraphiQL.ts#L17) option  a string that will be added to the request header object.
For example:
```js
import { graphiqlKoa } from 'apollo-server-koa';
router.get(
'/graphiql',
graphiqlKoa({
endpointURL: '/graphql',
passHeader: `'Authorization': 'Bearer lorem ipsum'`,
}),
);
```
## Principles
Apollo Server is built with the following principles in mind:
* **By the community, for the community**: Apollo Server's development is driven by the needs of developers
* **Simplicity**: by keeping things simple, Apollo Server is easier to use, easier to contribute to, and more secure
* **Performance**: Apollo Server is well-tested and production-ready - no modifications needed
Anyone is welcome to contribute to Apollo 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!

View file

@ -1,47 +0,0 @@
{
"name": "apollo-server-koa",
"version": "2.0.0-beta.9",
"description": "Production-ready Node.js GraphQL server for Koa",
"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-koa"
},
"keywords": [
"GraphQL",
"Apollo",
"Koa",
"Server",
"Javascript"
],
"author": "Jonas Helfer <jonas@helfer.email>",
"license": "MIT",
"bugs": {
"url": "https://github.com/apollographql/apollo-server/issues"
},
"homepage": "https://github.com/apollographql/apollo-server#readme",
"engines": {
"node": ">=8"
},
"dependencies": {
"apollo-server-core": "^2.0.0-beta.9",
"apollo-server-module-graphiql": "^2.0.0-beta.8"
},
"devDependencies": {
"@types/koa": "2.0.45",
"@types/koa-bodyparser": "4.2.0",
"@types/koa-router": "7.0.28",
"apollo-server-integration-testsuite": "^2.0.0-beta.9",
"koa": "2.5.1",
"koa-bodyparser": "4.2.0",
"koa-router": "7.4.0"
},
"typings": "dist/index.d.ts",
"typescript": {
"definition": "dist/index.d.ts"
}
}

View file

@ -1,7 +0,0 @@
export {
KoaGraphQLOptionsFunction,
KoaHandler,
KoaGraphiQLOptionsFunction,
graphqlKoa,
graphiqlKoa,
} from './koaApollo';

View file

@ -1,53 +0,0 @@
import koa from 'koa';
import koaRouter from 'koa-router';
import koaBody from 'koa-bodyparser';
import { graphqlKoa, graphiqlKoa } from './koaApollo';
import { GraphQLOptions } from 'apollo-server-core';
import { expect } from 'chai';
import http from 'http';
import testSuite, {
schema as Schema,
CreateAppOptions,
} from 'apollo-server-integration-testsuite';
function createApp(options: CreateAppOptions = {}) {
const app = new koa();
const router = new koaRouter();
options.graphqlOptions = options.graphqlOptions || { schema: Schema };
if (!options.excludeParser) {
app.use(koaBody());
}
if (options.graphiqlOptions) {
router.get('/graphiql', graphiqlKoa(options.graphiqlOptions));
}
router.get('/graphql', graphqlKoa(options.graphqlOptions));
router.post('/graphql', graphqlKoa(options.graphqlOptions));
app.use(router.routes());
app.use(router.allowedMethods());
return http.createServer(app.callback());
}
function destroyApp(app) {
app.close();
}
describe('koaApollo', () => {
it('throws error if called without schema', function() {
expect(() => graphqlKoa(undefined as GraphQLOptions)).to.throw(
'Apollo Server requires options.',
);
});
it('throws an error if called with more than one argument', function() {
expect(() => (<any>graphqlKoa)({}, 'x')).to.throw(
'Apollo Server expects exactly one argument, got 2',
);
});
});
describe('integration:Koa', () => {
testSuite(createApp, destroyApp);
});

View file

@ -1,85 +0,0 @@
import koa from 'koa';
import {
GraphQLOptions,
HttpQueryError,
runHttpQuery,
convertNodeHttpToRequest,
} from 'apollo-server-core';
import * as GraphiQL from 'apollo-server-module-graphiql';
export interface KoaGraphQLOptionsFunction {
(ctx: koa.Context): GraphQLOptions | Promise<GraphQLOptions>;
}
export interface KoaHandler {
(req: any, next): void;
}
export function graphqlKoa(
options: GraphQLOptions | KoaGraphQLOptionsFunction,
): KoaHandler {
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}`,
);
}
const graphqlHandler = (ctx: koa.Context): Promise<void> => {
return runHttpQuery([ctx], {
method: ctx.request.method,
options: options,
query:
ctx.request.method === 'POST' ? ctx.request.body : ctx.request.query,
request: convertNodeHttpToRequest(ctx.req),
}).then(
gqlResponse => {
ctx.set('Content-Type', 'application/json');
ctx.body = gqlResponse;
},
(error: HttpQueryError) => {
if ('HttpQueryError' !== error.name) {
throw error;
}
if (error.headers) {
Object.keys(error.headers).forEach(header => {
ctx.set(header, error.headers[header]);
});
}
ctx.status = error.statusCode;
ctx.body = error.message;
},
);
};
return graphqlHandler;
}
export interface KoaGraphiQLOptionsFunction {
(ctx: koa.Context): GraphiQL.GraphiQLData | Promise<GraphiQL.GraphiQLData>;
}
export function graphiqlKoa(
options: GraphiQL.GraphiQLData | KoaGraphiQLOptionsFunction,
) {
const graphiqlHandler = (ctx: koa.Context) => {
const query = ctx.request.query;
return GraphiQL.resolveGraphiQLString(query, options, ctx).then(
graphiqlString => {
ctx.set('Content-Type', 'text/html');
ctx.body = graphiqlString;
},
error => {
ctx.status = 500;
ctx.body = error.message;
},
);
};
return graphiqlHandler;
}

View file

@ -1,9 +0,0 @@
{
"extends": "../../tsconfig",
"compilerOptions": {
"rootDir": "./src",
"outDir": "./dist",
"types": []
},
"exclude": ["node_modules", "dist"]
}

View file

@ -1,6 +0,0 @@
*
!src/**/*
!dist/**/*
dist/**/*.test.*
!package.json
!README.md

View file

@ -1,167 +0,0 @@
---
title: Lambda
description: Setting up Apollo Server with Lambda
---
[![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 AWS Lambda integration for the Apollo community GraphQL Server. [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-lambda
```
<h2 id="deploying" title="Deploying with SAM">Deploying with AWS Serverless Application Model (SAM)</h2>
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/).
#### 1. Write the API handlers
```js
// graphql.js
var server = require('apollo-server-lambda'),
myGraphQLSchema = require('./schema');
exports.graphqlHandler = server.graphqlLambda({ schema: myGraphQLSchema });
exports.graphiqlHandler = server.graphiqlLambda({
endpointURL: '/Prod/graphql',
});
```
#### 2. Create an S3 bucket
The bucket name must be universally unique.
```shell
aws s3 mb s3://<bucket name>
```
#### 3. Create the Template
This will look for a file called graphql.js with two exports: `graphqlHandler` and `graphiqlHandler`. It creates two API endpoints:
* `/graphql` (GET and POST)
* `/graphiql` (GET)
In a file called `template.yaml`:
```yaml
AWSTemplateFormatVersion: '2010-09-09'
Transform: AWS::Serverless-2016-10-31
Resources:
GraphQL:
Type: AWS::Serverless::Function
Properties:
Handler: graphql.graphqlHandler
Runtime: nodejs6.10
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: nodejs6.10
Events:
GetRequest:
Type: Api
Properties:
Path: /graphiql
Method: get
```
#### 4. Package 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.
```sh
aws cloudformation package \
--template-file template.yaml \
--output-template-file serverless-output.yaml \
--s3-bucket <bucket-name>
```
#### 5. 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
```
<h2 id="request-info" title="Getting request info">Getting request info</h2>
To read information about the current request from the API Gateway event (HTTP headers, HTTP method, body, path, ...) or the current Lambda Context (Function Name, Function Version, awsRequestId, time remaning, ...) use the options function. This way they can be passed to your schema resolvers using the context option.
```js
var server = require('apollo-server-lambda'),
myGraphQLSchema = require('./schema');
exports.graphqlHandler = server.graphqlLambda((event, context) => {
const headers = event.headers,
functionName = context.functionName;
return {
schema: myGraphQLSchema,
context: {
headers,
functionName,
event,
context,
},
};
});
```
<h2 id="modifying-response" title="Modifying the response">Modifying the Lambda Response (Enable CORS)</h2>
To enable CORS the response HTTP headers need to be modified. To accomplish this pass in a callback filter to the generated handler of graphqlLambda.
```js
var server = require('apollo-server-lambda'),
myGraphQLSchema = require('./schema');
exports.graphqlHandler = function(event, context, callback) {
const callbackFilter = function(error, output) {
output.headers['Access-Control-Allow-Origin'] = '*';
callback(error, output);
};
const handler = server.graphqlLambda({ schema: myGraphQLSchema });
return handler(event, context, callbackFilter);
};
```
To enable CORS response for requests with credentials (cookies, http authentication) the allow origin header must equal the request origin and the allow credential header must be set to true.
```js
const CORS_ORIGIN = 'https://example.com';
var server = require('apollo-server-lambda'),
myGraphQLSchema = require('./schema');
exports.graphqlHandler = function(event, context, callback) {
const requestOrigin = event.headers.origin,
callbackFilter = function(error, output) {
if (requestOrigin === CORS_ORIGIN) {
output.headers['Access-Control-Allow-Origin'] = CORS_ORIGIN;
output.headers['Access-Control-Allow-Credentials'] = 'true';
}
callback(error, output);
};
const handler = server.graphqlLambda({ schema: myGraphQLSchema });
return handler(event, context, callbackFilter);
};
```

View file

@ -1,42 +0,0 @@
{
"name": "apollo-server-lambda",
"version": "2.0.0-beta.9",
"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/apollographql/apollo-server/tree/master/packages/apollo-server-lambda"
},
"keywords": [
"GraphQL",
"Apollo",
"Server",
"Lambda",
"Javascript"
],
"author": "Jonas Helfer <jonas@helfer.email>",
"license": "MIT",
"bugs": {
"url": "https://github.com/apollographql/apollo-server/issues"
},
"homepage": "https://github.com/apollographql/apollo-server#readme",
"engines": {
"node": ">=8"
},
"dependencies": {
"apollo-server-core": "^2.0.0-beta.9",
"apollo-server-module-graphiql": "^2.0.0-beta.8"
},
"devDependencies": {
"@types/aws-lambda": "8.10.3",
"apollo-server-integration-testsuite": "^2.0.0-beta.9"
},
"typings": "dist/index.d.ts",
"typescript": {
"definition": "dist/index.d.ts"
}
}

View file

@ -1,8 +0,0 @@
export {
LambdaHandler,
IHeaders,
LambdaGraphQLOptionsFunction,
LambdaGraphiQLOptionsFunction,
graphqlLambda,
graphiqlLambda,
} from './lambdaApollo';

View file

@ -1,75 +0,0 @@
import { graphqlLambda, graphiqlLambda } from './lambdaApollo';
import testSuite, {
schema as Schema,
CreateAppOptions,
} from 'apollo-server-integration-testsuite';
import { expect } from 'chai';
import { GraphQLOptions } from 'apollo-server-core';
import 'mocha';
import url from 'url';
function createLambda(options: CreateAppOptions = {}) {
let route, handler, callback, event, context;
options.graphqlOptions = options.graphqlOptions || { schema: Schema };
if (options.graphiqlOptions) {
route = '/graphiql';
handler = graphiqlLambda(options.graphiqlOptions);
} else {
route = '/graphql';
handler = graphqlLambda(options.graphqlOptions);
}
return function(req, res) {
if (!req.url.startsWith(route)) {
res.statusCode = 404;
res.end();
return;
}
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(_, 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(() => (<any>graphqlLambda)({}, {})).to.throw(
'Apollo Server expects exactly one argument, got 2',
);
});
});
describe('integration:Lambda', () => {
testSuite(createLambda);
});

View file

@ -1,127 +0,0 @@
import lambda from 'aws-lambda';
import { GraphQLOptions, runHttpQuery } from 'apollo-server-core';
import * as GraphiQL from 'apollo-server-module-graphiql';
export interface LambdaGraphQLOptionsFunction {
(event: any, context: lambda.Context):
| GraphQLOptions
| Promise<GraphQLOptions>;
}
// 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}`,
);
}
const graphqlHandler = 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,
request: event,
});
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,
});
}
};
return graphqlHandler;
}
export interface LambdaGraphiQLOptionsFunction {
(event: any, context: lambda.Context):
| GraphiQL.GraphiQLData
| Promise<GraphiQL.GraphiQLData>;
}
/* 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 | LambdaGraphiQLOptionsFunction,
) {
const graphiqlHandler = (
event,
lambdaContext: lambda.Context,
callback: lambda.Callback,
) => {
const query = event.queryStringParameters;
GraphiQL.resolveGraphiQLString(query, options, event, lambdaContext).then(
graphiqlString => {
callback(null, {
statusCode: 200,
headers: {
'Content-Type': 'text/html',
},
body: graphiqlString,
});
},
error => {
callback(null, {
statusCode: 500,
body: error.message,
});
},
);
};
return graphiqlHandler;
}

View file

@ -1,8 +0,0 @@
{
"extends": "../../tsconfig",
"compilerOptions": {
"rootDir": "./src",
"outDir": "./dist"
},
"exclude": ["node_modules", "dist"]
}

View file

@ -1,6 +0,0 @@
*
!src/**/*
!dist/**/*
dist/**/*.test.*
!package.json
!README.md

View file

@ -1,35 +0,0 @@
---
title: Micro
description: Setting up Apollo Server with Micro
---
[![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 [Micro](https://github.com/zeit/micro) integration for the Apollo community GraphQL Server. [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-micro
```
## Example
```js
import { microGraphiql, microGraphql } from 'apollo-server-micro';
import micro, { send } from 'micro';
import { get, post, router } from 'microrouter';
import schema from './schema';
const graphqlHandler = microGraphql({ schema });
const graphiqlHandler = microGraphiql({ endpointURL: '/graphql' });
const server = micro(
router(
get('/graphql', graphqlHandler),
post('/graphql', graphqlHandler),
get('/graphiql', graphiqlHandler),
(req, res) => send(res, 404, 'not found'),
),
);
server.listen(3000);
```

View file

@ -1,47 +0,0 @@
{
"name": "apollo-server-micro",
"version": "2.0.0-beta.9",
"description": "Production-ready Node.js GraphQL server for Micro",
"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-micro"
},
"keywords": [
"GraphQL",
"Apollo",
"Micro",
"Server",
"Javascript"
],
"author": "Nick Nance <nance.nick@gmail.email>",
"license": "MIT",
"bugs": {
"url": "https://github.com/apollographql/apollo-server/issues"
},
"homepage": "https://github.com/apollographql/apollo-server#readme",
"engines": {
"node": ">=8"
},
"dependencies": {
"apollo-server-core": "^2.0.0-beta.9",
"apollo-server-module-graphiql": "^2.0.0-beta.8"
},
"devDependencies": {
"@types/micro": "7.3.1",
"apollo-server-integration-testsuite": "^2.0.0-beta.9",
"micro": "8.0.4",
"microrouter": "2.2.3"
},
"peerDependencies": {
"micro": "^8.0.1 || ^9.0.1"
},
"typings": "dist/index.d.ts",
"typescript": {
"definition": "dist/index.d.ts"
}
}

View file

@ -1,6 +0,0 @@
export {
MicroGraphQLOptionsFunction,
MicroGraphiQLOptionsFunction,
microGraphql,
microGraphiql,
} from './microApollo';

View file

@ -1,54 +0,0 @@
import { microGraphql, microGraphiql } from './microApollo';
import 'mocha';
import micro, { send } from 'micro';
import {
router,
get,
post,
put,
patch,
del,
head,
options as opts,
} from 'microrouter';
import testSuite, {
schema,
CreateAppOptions,
} from 'apollo-server-integration-testsuite';
function createApp(options: CreateAppOptions) {
const graphqlOptions = (options && options.graphqlOptions) || { schema };
const graphiqlOptions = (options && options.graphiqlOptions) || {
endpointURL: '/graphql',
};
const graphqlHandler = microGraphql(graphqlOptions);
const graphiqlHandler = microGraphiql(graphiqlOptions);
return micro(
router(
get('/graphql', graphqlHandler),
post('/graphql', graphqlHandler),
put('/graphql', graphqlHandler),
patch('/graphql', graphqlHandler),
del('/graphql', graphqlHandler),
head('/graphql', graphqlHandler),
opts('/graphql', graphqlHandler),
get('/graphiql', graphiqlHandler),
post('/graphiql', graphiqlHandler),
put('/graphiql', graphiqlHandler),
patch('/graphiql', graphiqlHandler),
del('/graphiql', graphiqlHandler),
head('/graphiql', graphiqlHandler),
opts('/graphiql', graphiqlHandler),
(_, res) => send(res, 404, 'not found'),
),
);
}
describe('integration:Micro', () => {
testSuite(createApp);
});

View file

@ -1,96 +0,0 @@
import {
GraphQLOptions,
runHttpQuery,
convertNodeHttpToRequest,
} from 'apollo-server-core';
import * as GraphiQL from 'apollo-server-module-graphiql';
import { json, RequestHandler } from 'micro';
import url from 'url';
import { IncomingMessage, ServerResponse } from 'http';
export interface MicroGraphQLOptionsFunction {
(req?: IncomingMessage): GraphQLOptions | Promise<GraphQLOptions>;
}
export function microGraphql(
options: GraphQLOptions | MicroGraphQLOptionsFunction,
): RequestHandler {
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}`,
);
}
const graphqlHandler = async (req: IncomingMessage, res: ServerResponse) => {
let query;
if (req.method === 'POST') {
try {
query = await json(req);
} catch (err) {
query = undefined;
}
} else {
query = url.parse(req.url, true).query;
}
try {
const gqlResponse = await runHttpQuery([req, res], {
method: req.method,
options: options,
query: query,
request: convertNodeHttpToRequest(req),
});
res.setHeader('Content-Type', 'application/json');
return gqlResponse;
} catch (error) {
if ('HttpQueryError' === error.name) {
if (error.headers) {
Object.keys(error.headers).forEach(header => {
res.setHeader(header, error.headers[header]);
});
}
}
if (!error.statusCode) {
error.statusCode = 500;
}
throw error;
}
};
return graphqlHandler;
}
export interface MicroGraphiQLOptionsFunction {
(req?: IncomingMessage):
| GraphiQL.GraphiQLData
| Promise<GraphiQL.GraphiQLData>;
}
export function microGraphiql(
options: GraphiQL.GraphiQLData | MicroGraphiQLOptionsFunction,
): RequestHandler {
const graphiqlHandler = (req: IncomingMessage, res: ServerResponse) => {
const query = (req.url && url.parse(req.url, true).query) || {};
return GraphiQL.resolveGraphiQLString(query, options, req).then(
graphiqlString => {
res.setHeader('Content-Type', 'text/html');
res.write(graphiqlString);
res.end();
},
error => {
res.statusCode = 500;
res.write(error.message);
res.end();
},
);
};
return graphiqlHandler;
}

View file

@ -1,8 +0,0 @@
{
"extends": "../../tsconfig",
"compilerOptions": {
"rootDir": "./src",
"outDir": "./dist"
},
"exclude": ["node_modules", "dist"]
}

View file

@ -1,6 +0,0 @@
*
!src/**/*
!dist/**/*
dist/**/*.test.*
!package.json
!README.md

View file

@ -1,48 +0,0 @@
---
title: Restify
description: Setting up Apollo Server with Restify
---
[![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 Restify integration of Apollo Server. Apollo Server is a community-maintained open-source Apollo Server that works with all Node.js HTTP server frameworks: Express, Connect, Hapi, Koa and Restify. [Read the docs](https://www.apollographql.com/docs/apollo-server/).
```sh
npm install apollo-server-restify
```
## Usage
```js
import restify from 'restify';
import { graphqlRestify, graphiqlRestify } from 'apollo-server-restify';
const PORT = 3000;
const server = restify.createServer({
title: 'Apollo Server',
});
const graphQLOptions = { schema: myGraphQLSchema };
server.use(restify.plugins.bodyParser());
server.use(restify.plugins.queryParser());
server.post('/graphql', graphqlRestify(graphQLOptions));
server.get('/graphql', graphqlRestify(graphQLOptions));
server.get('/graphiql', graphiqlRestify({ endpointURL: '/graphql' }));
server.listen(PORT, () => console.log(`Listening on ${PORT}`));
```
## Principles
Apollo Server is built with the following principles in mind:
* **By the community, for the community**: Apollo Server's development is driven by the needs of developers
* **Simplicity**: by keeping things simple, Apollo Server is easier to use, easier to contribute to, and more secure
* **Performance**: Apollo Server is well-tested and production-ready - no modifications needed
Anyone is welcome to contribute to Apollo 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!
[Read the CHANGELOG.](https://github.com/apollographql/apollo-server/blob/master/CHANGELOG.md)

View file

@ -1,43 +0,0 @@
{
"name": "apollo-server-restify",
"version": "2.0.0-beta.9",
"description": "Production-ready Node.js GraphQL server for Restify",
"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-restify"
},
"keywords": [
"GraphQL",
"Apollo",
"Server",
"Restify",
"Javascript"
],
"author": "Jonas Helfer <jonas@helfer.email>",
"license": "MIT",
"bugs": {
"url": "https://github.com/apollographql/apollo-server/issues"
},
"homepage": "https://github.com/apollographql/apollo-server#readme",
"engines": {
"node": ">=8"
},
"dependencies": {
"apollo-server-core": "^2.0.0-beta.9",
"apollo-server-module-graphiql": "^2.0.0-beta.8"
},
"devDependencies": {
"@types/restify": "5.0.7",
"apollo-server-integration-testsuite": "^2.0.0-beta.9",
"restify": "5.2.1"
},
"typings": "dist/index.d.ts",
"typescript": {
"definition": "dist/index.d.ts"
}
}

View file

@ -1,7 +0,0 @@
export {
RestifyGraphQLOptionsFunction,
RestifyHandler,
RestifyGraphiQLOptionsFunction,
graphqlRestify,
graphiqlRestify,
} from './restifyApollo';

View file

@ -1,65 +0,0 @@
import 'mocha';
import testSuite, {
schema,
CreateAppOptions,
} from 'apollo-server-integration-testsuite';
import { expect } from 'chai';
import { GraphQLOptions } from 'apollo-server-core';
let restify, graphiqlRestify, graphqlRestify;
function createApp(options: CreateAppOptions = {}) {
const server = restify.createServer({
name: 'Restify Test Server',
});
options.graphqlOptions = options.graphqlOptions || { schema };
if (!options.excludeParser) {
server.use(restify.plugins.bodyParser());
server.use(restify.plugins.queryParser());
}
if (options.graphiqlOptions) {
server.get('/graphiql', graphiqlRestify(options.graphiqlOptions));
}
server.get('/graphql', graphqlRestify(options.graphqlOptions));
server.post('/graphql', graphqlRestify(options.graphqlOptions));
return server;
}
describe('graphqlRestify', () => {
// As was reported in https://github.com/apollographql/apollo-server/pull/921,
// Restify monkey-patches Node internals, which can have adverse affects on
// other environmental participants like Express. Therefore, restify is being
// dynamically loaded, rather than imported at top-level.
before(async () => {
const restifyApollo = await import('./restifyApollo');
restify = await import('restify');
graphqlRestify = restifyApollo.graphqlRestify;
graphiqlRestify = restifyApollo.graphiqlRestify;
});
it('throws error if called without schema', () => {
expect(() => graphqlRestify(undefined as GraphQLOptions)).to.throw(
'Apollo Server requires options.',
);
});
it('throws an error if called with more than one argument', () => {
expect(() => (<any>graphqlRestify)({}, 'x')).to.throw(
'Apollo Server expects exactly one argument, got 2',
);
});
it('generates a function if the options are ok', () => {
expect(() => graphqlRestify({ schema })).to.be.a('function');
});
});
describe('integration:Restify', () => {
testSuite(createApp);
});

View file

@ -1,121 +0,0 @@
import restify from 'restify';
import url from 'url';
import {
GraphQLOptions,
HttpQueryError,
runHttpQuery,
convertNodeHttpToRequest,
} from 'apollo-server-core';
import * as GraphiQL from 'apollo-server-module-graphiql';
export interface RestifyGraphQLOptionsFunction {
(req?: restify.Request, res?: restify.Response):
| GraphQLOptions
| Promise<GraphQLOptions>;
}
// Design principles:
// - You can issue a GET or POST with your query.
// - simple, fast and secure
//
export interface RestifyHandler {
(req: restify.Request, res: restify.Response, next: restify.Next): void;
}
export function graphqlRestify(
options: GraphQLOptions | RestifyGraphQLOptionsFunction,
): RestifyHandler {
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}`,
);
}
const graphqlHandler = (
req: restify.Request,
res: restify.Response,
next: restify.Next,
): void => {
runHttpQuery([req, res], {
method: req.method,
options: options,
query: req.method === 'POST' ? req.body : req.query,
request: convertNodeHttpToRequest(req),
}).then(
gqlResponse => {
res.setHeader('Content-Type', 'application/json');
res.write(gqlResponse);
res.end();
next();
},
(error: HttpQueryError) => {
if ('HttpQueryError' !== error.name) {
throw error;
}
if (error.headers) {
Object.keys(error.headers).forEach(header => {
res.setHeader(header, error.headers[header]);
});
}
res.statusCode = error.statusCode;
res.write(error.message);
res.end();
next(false);
},
);
};
return graphqlHandler;
}
export interface RestifyGraphiQLOptionsFunction {
(req?: restify.Request):
| GraphiQL.GraphiQLData
| Promise<GraphiQL.GraphiQLData>;
}
/* This middleware 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 graphiqlRestify(
options: GraphiQL.GraphiQLData | RestifyGraphiQLOptionsFunction,
) {
const graphiqlHandler = (
req: restify.Request,
res: restify.Response,
next: restify.Next,
) => {
const query = (req.url && url.parse(req.url, true).query) || {};
GraphiQL.resolveGraphiQLString(query, options, req).then(
graphiqlString => {
res.setHeader('Content-Type', 'text/html');
res.write(graphiqlString);
res.end();
next();
},
error => {
res.statusCode = 500;
res.write(error.message);
res.end();
next(false);
},
);
};
return graphiqlHandler;
}

View file

@ -1,9 +0,0 @@
{
"extends": "../../tsconfig",
"compilerOptions": {
"rootDir": "./src",
"outDir": "./dist",
"types": []
},
"exclude": ["node_modules", "dist"]
}

View file

@ -25,21 +25,9 @@ require('../packages/apollo-server-express/dist/ApolloServer.test.js');
//Apollo server 1 tests
require('../packages/apollo-server-module-operation-store/dist/operationStore.test');
NODE_MAJOR_VERSION >= 7 &&
require('../packages/apollo-server-adonis/dist/adonisApollo.test');
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+
NODE_MAJOR_VERSION >= 6 &&
require('../packages/apollo-server-micro/dist/microApollo.test');
NODE_MAJOR_VERSION >= 7 &&
require('../packages/apollo-server-koa/dist/koaApollo.test');
require('../packages/apollo-server-lambda/dist/lambdaApollo.test');
require('../packages/apollo-server-azure-functions/dist/azureFunctionsApollo.test');
require('../packages/apollo-server-express/dist/apolloServerHttp.test');
// XXX: Running restify last as it breaks http.
// for more info: https://github.com/restify/node-restify/issues/700
require('../packages/apollo-server-restify/dist/restifyApollo.test');