mirror of
https://github.com/vale981/apollo-server
synced 2025-03-05 09:41:40 -05:00
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:
parent
1fd3b216d0
commit
40f9a4982f
46 changed files with 5 additions and 1969 deletions
|
@ -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
|
||||
|
||||
[](https://badge.fury.io/js/apollo-server-core)
|
||||
[](https://circleci.com/gh/apollographql/apollo-cache-control-js)
|
||||
[](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
|
||||
|
|
|
@ -1,6 +0,0 @@
|
|||
*
|
||||
!src/**/*
|
||||
!dist/**/*
|
||||
dist/**/*.test.*
|
||||
!package.json
|
||||
!README.md
|
|
@ -1,78 +0,0 @@
|
|||
---
|
||||
title: Adonis
|
||||
description: Setting up Apollo Server with Adonis
|
||||
---
|
||||
|
||||
[](https://badge.fury.io/js/apollo-server-core) [](https://circleci.com/gh/apollographql/apollo-cache-control-js) [](https://coveralls.io/github/apollographql/apollo-server?branch=master) [](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!
|
|
@ -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"
|
||||
}
|
||||
}
|
|
@ -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);
|
||||
});
|
|
@ -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;
|
||||
}
|
|
@ -1,7 +0,0 @@
|
|||
export {
|
||||
AdonisGraphQLOptionsFunction,
|
||||
AdonisHandler,
|
||||
AdonisGraphiQLOptionsFunction,
|
||||
graphqlAdonis,
|
||||
graphiqlAdonis,
|
||||
} from './adonisApollo';
|
|
@ -1,8 +0,0 @@
|
|||
{
|
||||
"extends": "../../tsconfig",
|
||||
"compilerOptions": {
|
||||
"rootDir": "./src",
|
||||
"outDir": "./dist"
|
||||
},
|
||||
"exclude": ["node_modules", "dist"]
|
||||
}
|
|
@ -1,6 +0,0 @@
|
|||
*
|
||||
!dist
|
||||
!dist/**/*
|
||||
dist/**/*.test.*
|
||||
!package.json
|
||||
!README.md
|
|
@ -1,70 +0,0 @@
|
|||
---
|
||||
title: Azure Functions
|
||||
description: Setting up Apollo Server with Azure Functions
|
||||
---
|
||||
|
||||
[](https://badge.fury.io/js/apollo-server-core) [](https://travis-ci.org/apollographql/apollo-server) [](https://coveralls.io/github/apollographql/apollo-server?branch=master) [](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,
|
||||
);
|
||||
}
|
||||
```
|
|
@ -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"
|
||||
}
|
||||
}
|
|
@ -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);
|
||||
});
|
|
@ -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;
|
||||
}
|
|
@ -1,8 +0,0 @@
|
|||
export {
|
||||
AzureFunctionsHandler,
|
||||
IHeaders,
|
||||
AzureFunctionsGraphQLOptionsFunction,
|
||||
AzureFunctionsGraphiQLOptionsFunction,
|
||||
graphqlAzureFunctions,
|
||||
graphiqlAzureFunctions,
|
||||
} from './azureFunctionsApollo';
|
|
@ -1,8 +0,0 @@
|
|||
{
|
||||
"extends": "../../tsconfig",
|
||||
"compilerOptions": {
|
||||
"rootDir": "./src",
|
||||
"outDir": "./dist"
|
||||
},
|
||||
"exclude": ["node_modules", "dist"]
|
||||
}
|
|
@ -5,7 +5,7 @@ description: Setting up Apollo Server with Express.js or Connect
|
|||
|
||||
[](https://badge.fury.io/js/apollo-server-core) [](https://circleci.com/gh/apollographql/apollo-cache-control-js) [](https://coveralls.io/github/apollographql/apollo-server?branch=master) [](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
|
||||
|
|
|
@ -5,7 +5,7 @@ description: Setting up Apollo Server with Hapi
|
|||
|
||||
[](https://badge.fury.io/js/apollo-server-core) [](https://circleci.com/gh/apollographql/apollo-cache-control-js) [](https://coveralls.io/github/apollographql/apollo-server?branch=master) [](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
|
||||
|
|
|
@ -1,6 +0,0 @@
|
|||
*
|
||||
!src/**/*
|
||||
!dist/**/*
|
||||
dist/**/*.test.*
|
||||
!package.json
|
||||
!README.md
|
|
@ -1,77 +0,0 @@
|
|||
---
|
||||
title: Koa
|
||||
description: Setting up Apollo Server with Koa
|
||||
---
|
||||
|
||||
[](https://badge.fury.io/js/apollo-server-core) [](https://circleci.com/gh/apollographql/apollo-cache-control-js) [](https://coveralls.io/github/apollographql/apollo-server?branch=master) [](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!
|
|
@ -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"
|
||||
}
|
||||
}
|
|
@ -1,7 +0,0 @@
|
|||
export {
|
||||
KoaGraphQLOptionsFunction,
|
||||
KoaHandler,
|
||||
KoaGraphiQLOptionsFunction,
|
||||
graphqlKoa,
|
||||
graphiqlKoa,
|
||||
} from './koaApollo';
|
|
@ -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);
|
||||
});
|
|
@ -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;
|
||||
}
|
|
@ -1,9 +0,0 @@
|
|||
{
|
||||
"extends": "../../tsconfig",
|
||||
"compilerOptions": {
|
||||
"rootDir": "./src",
|
||||
"outDir": "./dist",
|
||||
"types": []
|
||||
},
|
||||
"exclude": ["node_modules", "dist"]
|
||||
}
|
|
@ -1,6 +0,0 @@
|
|||
*
|
||||
!src/**/*
|
||||
!dist/**/*
|
||||
dist/**/*.test.*
|
||||
!package.json
|
||||
!README.md
|
|
@ -1,167 +0,0 @@
|
|||
---
|
||||
title: Lambda
|
||||
description: Setting up Apollo Server with Lambda
|
||||
---
|
||||
|
||||
[](https://badge.fury.io/js/apollo-server-core) [](https://circleci.com/gh/apollographql/apollo-cache-control-js) [](https://coveralls.io/github/apollographql/apollo-server?branch=master) [](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);
|
||||
};
|
||||
```
|
|
@ -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"
|
||||
}
|
||||
}
|
|
@ -1,8 +0,0 @@
|
|||
export {
|
||||
LambdaHandler,
|
||||
IHeaders,
|
||||
LambdaGraphQLOptionsFunction,
|
||||
LambdaGraphiQLOptionsFunction,
|
||||
graphqlLambda,
|
||||
graphiqlLambda,
|
||||
} from './lambdaApollo';
|
|
@ -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);
|
||||
});
|
|
@ -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;
|
||||
}
|
|
@ -1,8 +0,0 @@
|
|||
{
|
||||
"extends": "../../tsconfig",
|
||||
"compilerOptions": {
|
||||
"rootDir": "./src",
|
||||
"outDir": "./dist"
|
||||
},
|
||||
"exclude": ["node_modules", "dist"]
|
||||
}
|
|
@ -1,6 +0,0 @@
|
|||
*
|
||||
!src/**/*
|
||||
!dist/**/*
|
||||
dist/**/*.test.*
|
||||
!package.json
|
||||
!README.md
|
|
@ -1,35 +0,0 @@
|
|||
---
|
||||
title: Micro
|
||||
description: Setting up Apollo Server with Micro
|
||||
---
|
||||
|
||||
[](https://badge.fury.io/js/apollo-server-core) [](https://circleci.com/gh/apollographql/apollo-cache-control-js) [](https://coveralls.io/github/apollographql/apollo-server?branch=master) [](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);
|
||||
```
|
|
@ -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"
|
||||
}
|
||||
}
|
|
@ -1,6 +0,0 @@
|
|||
export {
|
||||
MicroGraphQLOptionsFunction,
|
||||
MicroGraphiQLOptionsFunction,
|
||||
microGraphql,
|
||||
microGraphiql,
|
||||
} from './microApollo';
|
|
@ -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);
|
||||
});
|
|
@ -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;
|
||||
}
|
|
@ -1,8 +0,0 @@
|
|||
{
|
||||
"extends": "../../tsconfig",
|
||||
"compilerOptions": {
|
||||
"rootDir": "./src",
|
||||
"outDir": "./dist"
|
||||
},
|
||||
"exclude": ["node_modules", "dist"]
|
||||
}
|
|
@ -1,6 +0,0 @@
|
|||
*
|
||||
!src/**/*
|
||||
!dist/**/*
|
||||
dist/**/*.test.*
|
||||
!package.json
|
||||
!README.md
|
|
@ -1,48 +0,0 @@
|
|||
---
|
||||
title: Restify
|
||||
description: Setting up Apollo Server with Restify
|
||||
---
|
||||
|
||||
[](https://badge.fury.io/js/apollo-server-core) [](https://circleci.com/gh/apollographql/apollo-cache-control-js) [](https://coveralls.io/github/apollographql/apollo-server?branch=master) [](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)
|
|
@ -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"
|
||||
}
|
||||
}
|
|
@ -1,7 +0,0 @@
|
|||
export {
|
||||
RestifyGraphQLOptionsFunction,
|
||||
RestifyHandler,
|
||||
RestifyGraphiQLOptionsFunction,
|
||||
graphqlRestify,
|
||||
graphiqlRestify,
|
||||
} from './restifyApollo';
|
|
@ -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);
|
||||
});
|
|
@ -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;
|
||||
}
|
|
@ -1,9 +0,0 @@
|
|||
{
|
||||
"extends": "../../tsconfig",
|
||||
"compilerOptions": {
|
||||
"rootDir": "./src",
|
||||
"outDir": "./dist",
|
||||
"types": []
|
||||
},
|
||||
"exclude": ["node_modules", "dist"]
|
||||
}
|
|
@ -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');
|
||||
|
|
Loading…
Add table
Reference in a new issue