Skip to content

Commit

Permalink
WIP
Browse files Browse the repository at this point in the history
  • Loading branch information
NeoReyad committed Jan 24, 2017
1 parent 3d297c9 commit d96db0e
Show file tree
Hide file tree
Showing 5 changed files with 27 additions and 148 deletions.
4 changes: 2 additions & 2 deletions packages/graphql-server-lambda/package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "graphql-server-lambda",
"version": "0.4.3",
"version": "0.5.1",
"description": "Production-ready Node.js GraphQL server for AWS Lambda",
"main": "dist/index.js",
"scripts": {
Expand All @@ -25,7 +25,7 @@
},
"homepage": "https://github.com/apollostack/graphql-server#readme",
"dependencies": {
"graphql-server-core": "^0.5.0",
"graphql-server-core": "^0.5.1",
"graphql-server-module-graphiql": "^0.4.4"
},
"devDependencies": {
Expand Down
3 changes: 2 additions & 1 deletion packages/graphql-server-lambda/src/lambdaApollo.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,7 @@ function createLambda(options: CreateAppOptions = {}) {
};
context = {};
callback = function(error, result) {
console.log('Called callback');
res.statusCode = result.statusCode;
for (let key in result.headers) {
if (result.headers.hasOwnProperty(key)) {
Expand All @@ -52,7 +53,7 @@ describe('lambdaApollo', () => {

it('throws an error if called with more than one argument', function(){
expect(() => (<any>graphqlLambda)({}, {})).to.throw(
'Apollo Server expects exactly one arguments, got 2');
'Apollo Server expects exactly one argument, got 2');
});
});

Expand Down
165 changes: 21 additions & 144 deletions packages/graphql-server-lambda/src/lambdaApollo.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,6 @@
import * as lambda from 'aws-lambda';
import * as graphql from 'graphql';
import * as url from 'url';
import { GraphQLOptions, runQuery } from 'graphql-server-core';
import { GraphQLOptions, runHttpQuery } from 'graphql-server-core';
import * as GraphiQL from 'graphql-server-module-graphiql';

export interface LambdaGraphQLOptionsFunction {
Expand All @@ -26,168 +25,46 @@ export function graphqlLambda( options: GraphQLOptions | LambdaGraphQLOptionsFun
throw new Error('Apollo Server requires options.');
}

if (arguments.length > 2) {
if (arguments.length > 1) {
throw new Error(`Apollo Server expects exactly one argument, got ${arguments.length}`);
}

return async (event, lambdaContext: lambda.Context, callback: lambda.Callback) => {
const headers: string[] = [];
let optionsObject: GraphQLOptions;
if (isOptionsFunction(options)) {
try {
optionsObject = await options(event, lambdaContext);
} catch (e) {
callback(
null,
{
'statusCode': 500,
'headers': headers,
'body': `Invalid options provided to ApolloServer: ${e.message}`,
},
);
return;
}
} else {
optionsObject = options;
}

const formatErrorFn = optionsObject.formatError || graphql.formatError;

if (event.httpMethod !== 'POST') {
headers['Allow'] = 'Post';
callback(
null,
{
'statusCode': 405,
'headers': headers,
'body': 'Apollo Server supports only POST requests.',
},
);
return;
}
const query = event.httpMethod === 'POST' ? JSON.parse(event.body) : event.queryStringParameters;
let statusCode: number = null,
gqlResponse = null,
headers: string[] = [];

if (!event.body) {
callback(
null,
{
'statusCode': 500,
'headers': headers,
'body': 'POST body missing.',
},
);
return;
}

let b;
try {
b = JSON.parse(event.body);
console.log(query);
gqlResponse = await runHttpQuery([event, lambdaContext], {
method: event.httpMethod,
options: options,
query: query,
});
headers['Content-Type'] = 'application/json';
statusCode = 200;
} catch (error) {
callback(
null,
{
'statusCode': 500,
'headers': headers,
'body': 'POST body is invalid JSON.',
},
);
return;
}
let isBatch = true;
// TODO: do something different here if the body is an array.
// Throw an error if body isn't either array or object.
if (!Array.isArray(b)) {
isBatch = false;
b = [b];
}

let responses: Array<graphql.GraphQLResult> = [];
for (let requestParams of b) {
try {
const query = requestParams.query;
const operationName = requestParams.operationName;
let variables = requestParams.variables;

if (typeof variables === 'string') {
try {
variables = JSON.parse(variables);
} catch (error) {
callback(
null,
{
'statusCode': 400,
'headers': headers,
'body': 'Variables are invalid JSON.',
},
);
return;
}
}

// Shallow clone context for queries in batches. This allows
// users to distinguish multiple queries in the batch and to
// modify the context object without interfering with each other.
let context = optionsObject.context;
if (isBatch) {
context = Object.assign({}, context || {});
}

let params = {
schema: optionsObject.schema,
query: query,
variables: variables,
context: context,
rootValue: optionsObject.rootValue,
operationName: operationName,
logFunction: optionsObject.logFunction,
validationRules: optionsObject.validationRules,
formatError: formatErrorFn,
formatResponse: optionsObject.formatResponse,
debug: optionsObject.debug,
};

if (optionsObject.formatParams) {
params = optionsObject.formatParams(params);
}

responses.push(await runQuery(params));
} catch (e) {
responses.push({ errors: [formatErrorFn(e)] });
if ( 'HttpQueryError' !== error.name ) {
throw error;
}
}

let statusCode = 200;
headers['Content-Type'] = 'application/json';
if (isBatch) {
headers = error.headers;
statusCode = error.statusCode;
gqlResponse = error.response;
} finally {
callback(
null,
{
'statusCode': statusCode,
'headers': headers,
'body': JSON.stringify(responses),
},
);
} else {
const gqlResponse = responses[0];
if (gqlResponse.errors && typeof gqlResponse.data === 'undefined') {
statusCode = 400;
}
callback(
null,
{
'statusCode': statusCode,
'headers': headers,
'body': JSON.stringify(gqlResponse),
'body': gqlResponse,
},
);
}

};
}

function isOptionsFunction(arg: GraphQLOptions | LambdaGraphQLOptionsFunction): arg is LambdaGraphQLOptionsFunction {
return typeof arg === 'function';
}

/* This Lambda Function Handler returns the html for the GraphiQL interactive query UI
*
* GraphiQLData arguments
Expand Down
2 changes: 1 addition & 1 deletion packages/graphql-server-lambda/tsconfig.json
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@
"node_modules/@types"
],
"types": [
"typed-graphql",
"@types/graphql",
"@types/node"
]
},
Expand Down
1 change: 1 addition & 0 deletions test/tests.js
Original file line number Diff line number Diff line change
Expand Up @@ -11,3 +11,4 @@ require('../packages/graphql-server-express/dist/connectApollo.test');
require('../packages/graphql-server-hapi/dist/hapiApollo.test');
require('../packages/graphql-server-koa/dist/koaApollo.test');
require('../packages/graphql-server-express/dist/apolloServerHttp.test');
require('../packages/graphql-server-lambda/dist/lambdaApollo.test');

0 comments on commit d96db0e

Please sign in to comment.