2016-06-12 22:41:46 -07:00
|
|
|
import * as express from 'express';
|
|
|
|
import * as graphql from 'graphql';
|
2016-06-14 12:03:53 -07:00
|
|
|
import { runQuery } from '../core/runQuery';
|
2016-06-12 22:41:46 -07:00
|
|
|
|
2016-06-15 20:35:48 -07:00
|
|
|
import { renderGraphiQL, GraphiQLData } from '../modules/renderGraphiQL';
|
|
|
|
|
|
|
|
// TODO: will these be the same or different for other integrations?
|
|
|
|
export interface ExpressApolloOptions {
|
2016-06-12 22:41:46 -07:00
|
|
|
schema: graphql.GraphQLSchema;
|
2016-06-15 20:35:48 -07:00
|
|
|
formatError?: Function;
|
|
|
|
rootValue?: any;
|
|
|
|
context?: any;
|
|
|
|
logFunction?: Function;
|
|
|
|
// TODO: does this need to be able to take a promise as well, like express-graphql does?
|
|
|
|
// answer: yes, it does. Func(req) => options
|
2016-06-12 22:41:46 -07:00
|
|
|
}
|
|
|
|
|
2016-06-15 20:35:48 -07:00
|
|
|
export function graphqlHTTP(options: ExpressApolloOptions) {
|
2016-06-12 22:41:46 -07:00
|
|
|
if (!options) {
|
2016-06-15 20:35:48 -07:00
|
|
|
throw new Error('Apollo graphqlHTTP middleware requires options.');
|
2016-06-12 22:41:46 -07:00
|
|
|
}
|
2016-06-14 12:03:53 -07:00
|
|
|
|
2016-06-12 22:41:46 -07:00
|
|
|
if (arguments.length > 1) {
|
|
|
|
throw new Error(`apolloServer expects exactly one argument, got ${arguments.length + 1}`);
|
|
|
|
}
|
2016-06-14 12:03:53 -07:00
|
|
|
|
2016-06-12 22:41:46 -07:00
|
|
|
return (req: express.Request, res: express.Response, next) => {
|
2016-06-17 15:45:35 -07:00
|
|
|
return runQuery({
|
2016-06-14 12:03:53 -07:00
|
|
|
schema: options.schema,
|
2016-06-17 15:45:35 -07:00
|
|
|
query: getQueryString(req),
|
2016-06-14 12:03:53 -07:00
|
|
|
}).then(gqlResponse => {
|
|
|
|
res.set('Content-Type', 'application/json');
|
2016-06-15 20:35:48 -07:00
|
|
|
res.send({ data: gqlResponse.data, errors: gqlResponse.errors });
|
|
|
|
});
|
|
|
|
};
|
|
|
|
}
|
|
|
|
|
2016-06-17 15:45:35 -07:00
|
|
|
function getQueryString(req: express.Request): string {
|
|
|
|
if (req.method === 'POST') {
|
|
|
|
return req.body;
|
|
|
|
} else if (req.method === 'GET') {
|
|
|
|
return req.query['query'];
|
|
|
|
}
|
|
|
|
throw new Error(`HTTP method ${req.method} not supported`);
|
|
|
|
}
|
|
|
|
|
2016-06-15 20:35:48 -07:00
|
|
|
// this returns the html for the GraphiQL interactive query UI
|
|
|
|
// TODO: it's still missing a way to tell it where the GraphQL endpoint is.
|
|
|
|
export function renderGraphiQL(options: GraphiQLData) {
|
|
|
|
return (req: express.Request, res: express.Response, next) => {
|
|
|
|
const graphiQLString = renderGraphiQL({
|
|
|
|
query: options.query,
|
|
|
|
variables: options.variables,
|
|
|
|
operationName: options.operationName,
|
|
|
|
result: options.result,
|
2016-06-14 12:03:53 -07:00
|
|
|
});
|
2016-06-15 20:35:48 -07:00
|
|
|
res.set('Content-Type', 'text/html');
|
|
|
|
res.send(graphiQLString);
|
2016-06-14 12:03:53 -07:00
|
|
|
};
|
2016-06-12 22:41:46 -07:00
|
|
|
}
|