Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Zeit micro support #347

Merged
merged 13 commits into from
Apr 8, 2017
1 change: 0 additions & 1 deletion .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,6 @@ build/Release

# Dependency directory
node_modules
typings
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

why? :O

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

isn't this old / left over from the old typings from the old version of typescript?

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yep, but sometimes people still downloading typings locally, just wanted to make sure you didnt remove this to commit typings into the repo


# Optional npm cache directory
.npm
Expand Down
1 change: 1 addition & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@
* Restify: Fix for calling next() ([@jadkap](https://github.com/jadkap)) on [#285](https://github.com/apollostack/graphql-server/pull/285)
* Update GraphiQL to version 0.9.1 ([@ephemer](https://github.com/ephemer)) on [#293](https://github.com/apollostack/graphql-server/pull/293)
* Add AWS Lambda Integration [#101](https://github.com/apollostack/graphql-server/issues/101)
* Add Zeit Micro Integration [#324](https://github.com/apollographql/graphql-server/issues/324)
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Have we really not released since adding AWS lamdba or did we (I?) just forget to update the changelog with the latest version?


### v0.5.2
* **Restify integration** ([@joelgriffith](https://github.com/joelgriffith)) on [#189](https://github.com/apollostack/graphql-server/pull/189)
Expand Down
11 changes: 11 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,7 @@ where variant is one of the following:
- hapi
- restify
- lambda
- [micro](https://github.com/zeit/micro)

### Express

Expand Down Expand Up @@ -165,6 +166,16 @@ var server = require("graphql-server-lambda");
exports.handler = server.graphqlLambda({ schema: myGraphQLSchema });
```

### Zeit Micro

Micro function requires the micro module

```js
var server = require("graphql-server-micro");

module.exports = server.microGraphql({ schema: myGraphQLSchema });
```

## Options

GraphQL Server can be configured with an options object with the the following fields:
Expand Down
5 changes: 5 additions & 0 deletions packages/graphql-server-micro/.npmignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
*
!dist
!dist/**/*
dist/**/*.test.*
!package.json
3 changes: 3 additions & 0 deletions packages/graphql-server-micro/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
# graphql-server-micro

This is the [Micro](https://github.com/zeit/micro) integration for the Apollo community GraphQL Server. [Read the docs.](http://dev.apollodata.com/tools/apollo-server/index.html)
46 changes: 46 additions & 0 deletions packages/graphql-server-micro/package.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,46 @@
{
"name": "graphql-server-micro",
"version": "0.5.1",
"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/apollostack/graphql-server/tree/master/packages/graphql-server-micro"
},
"keywords": [
"GraphQL",
"Apollo",
"Micro",
"Server",
"Javascript"
],
"author": "Nick Nance <[email protected]>",
"license": "MIT",
"bugs": {
"url": "https://github.com/apollostack/graphql-server/issues"
},
"homepage": "https://github.com/apollostack/graphql-server#readme",
"dependencies": {
"graphql-server-core": "^0.6.0",
"graphql-server-module-graphiql": "^0.6.0"
},
"devDependencies": {
"graphql-server-integration-testsuite": "^0.6.0",
"micro": "^7.3.0"
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

does micro package has embeded typings?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

no

},
"peerDependencies": {
"graphql": "^0.8.0 || ^0.9.0",
"micro": "^7.3.0"
},
"optionalDependencies": {
"@types/graphql": "^0.9.0"
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

and @types/micro if such needed (see question above :))

},
"typings": "dist/index.d.ts",
"typescript": {
"definition": "dist/index.d.ts"
}
}
2 changes: 2 additions & 0 deletions packages/graphql-server-micro/src/index.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
export { MicroGraphQLOptionsFunction,
microGraphql, microGraphiql } from './microApollo';
18 changes: 18 additions & 0 deletions packages/graphql-server-micro/src/microApollo.test.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
import { microGraphql, microGraphiql } from './microApollo';
import 'mocha';

import * as micro from 'micro';
import testSuite, { schema as Schema, CreateAppOptions } from 'graphql-server-integration-testsuite';

function createApp(options: CreateAppOptions) {
if (options && options.graphiqlOptions ) {
return micro(microGraphiql( options.graphiqlOptions ));
} else {
const graphqlOptions = (options && options.graphqlOptions) || { schema: Schema };
return micro(microGraphql(graphqlOptions));
}
}

describe('integration:Micro', () => {
testSuite(createApp);
});
75 changes: 75 additions & 0 deletions packages/graphql-server-micro/src/microApollo.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,75 @@
import { GraphQLOptions, HttpQueryError, runHttpQuery } from 'graphql-server-core';
import * as GraphiQL from 'graphql-server-module-graphiql';
import { json } from 'micro';
import * as url from 'url';
import {IncomingMessage, ServerResponse} from 'http';

export interface MicroGraphQLOptionsFunction {
(req?: IncomingMessage): GraphQLOptions | Promise<GraphQLOptions>;
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

why the req parameter is considered optional?

}

export function microGraphql(options: GraphQLOptions | MicroGraphQLOptionsFunction) {
if (!options) {
throw new Error('Apollo Server requires options.');
}

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

return async function (req: IncomingMessage, res: ServerResponse) {
let query;
if (req.method === 'POST') {
try {
query = await json(req);
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

await on json? oh?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

json is a function supplied with micro that is an async parser. the reason it is async is because it will use the request as a stream and will return the complete json once the full request payload is received.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Oh cool :)

} catch (err) {
query = undefined;
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

and then? i mean, where do you expect the server to respond with an error?

Copy link
Contributor Author

@nnance nnance Apr 3, 2017

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

actually by setting query to undefined it causes the runHttpQuery function to trigger an error. This is fundamentally what happens with the express middleware when the body is empty or not parsable

}
} else {
query = url.parse(req.url, true).query;
}

runHttpQuery([req, res], {
method: req.method,
options: options,
query: query,
}).then((gqlResponse) => {
res.setHeader('Content-Type', 'application/json');
res.write(gqlResponse);
res.end();
}, (error: HttpQueryError) => {
if ( 'HttpQueryError' !== error.name ) {
throw error;
}

if ( error.headers ) {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Is this something we added recently? I don't remember having this in the initial versions. What are people using those headers for?

Object.keys(error.headers).forEach((header) => {
res.setHeader(header, error.headers[header]);
});
}

res.statusCode = error.statusCode;
res.write(error.message);
res.end();
});
};
}

export function microGraphiql(options: GraphiQL.GraphiQLData) {
return (req: IncomingMessage, res: ServerResponse) => {
const q = req.url && url.parse(req.url, true).query || {};
const query = q.query || '';
const operationName = q.operationName || '';

const graphiQLString = GraphiQL.renderGraphiQL({
endpointURL: options.endpointURL,
query: query || options.query,
variables: q.variables && JSON.parse(q.variables) || options.variables,
operationName: operationName || options.operationName,
passHeader: options.passHeader,
});
res.setHeader('Content-Type', 'text/html');
res.write(graphiQLString);
res.end();
};
}
14 changes: 14 additions & 0 deletions packages/graphql-server-micro/tsconfig.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
{
"extends": "../../tsconfig",
"compilerOptions": {
"rootDir": "./src",
"outDir": "./dist",
"typeRoots": [
"node_modules/@types"
]
},
"exclude": [
"node_modules",
"dist"
]
}
1 change: 1 addition & 0 deletions test/tests.js
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ require('../packages/graphql-server-express/dist/connectApollo.test');
require('../packages/graphql-server-hapi/dist/hapiApollo.test');
if (NODE_MAJOR_VERSION >= 6) {
require('../packages/graphql-server-koa/dist/koaApollo.test');
require('../packages/graphql-server-micro/dist/microApollo.test');
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

micro does not support es5?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

no. it uses async await.

}
require('../packages/graphql-server-restify/dist/restifyApollo.test');
require('../packages/graphql-server-lambda/dist/lambdaApollo.test');
Expand Down