mirror of
https://github.com/vale981/apollo-server
synced 2025-03-05 09:41:40 -05:00
Core refactor hapi (#36)
* Revert "get supertest working for TS"
This reverts commit 300b32fa5a
.
* initial hapi plugin
* working hapi server
* update exports for es6 support
This commit is contained in:
parent
300b32fa5a
commit
f6f25c611e
8 changed files with 90 additions and 46 deletions
|
@ -41,6 +41,7 @@
|
||||||
"es6-promise": "^3.2.1",
|
"es6-promise": "^3.2.1",
|
||||||
"express": "^4.13.4",
|
"express": "^4.13.4",
|
||||||
"graphql": "^0.6.0",
|
"graphql": "^0.6.0",
|
||||||
|
"hapi": "^13.4.1",
|
||||||
"source-map-support": "^0.4.0"
|
"source-map-support": "^0.4.0"
|
||||||
},
|
},
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
|
|
|
@ -7,58 +7,51 @@ import {
|
||||||
execute,
|
execute,
|
||||||
} from 'graphql';
|
} from 'graphql';
|
||||||
|
|
||||||
import { Promise } from 'es6-promise';
|
|
||||||
|
|
||||||
export interface GqlResponse {
|
export interface GqlResponse {
|
||||||
data?: Object;
|
data?: Object;
|
||||||
errors?: Array<string>;
|
errors?: Array<string>;
|
||||||
}
|
}
|
||||||
|
|
||||||
function runQuery({
|
export interface QueryOptions {
|
||||||
schema,
|
schema: GraphQLSchema;
|
||||||
query,
|
query: string | Document;
|
||||||
rootValue,
|
rootValue?: any;
|
||||||
context,
|
context?: any;
|
||||||
variables,
|
variables?: { [key: string]: any };
|
||||||
operationName,
|
operationName?: string;
|
||||||
}: {
|
//logFunction?: function => void
|
||||||
schema: GraphQLSchema,
|
//validationRules?: No, too risky. If you want extra validation rules, then parse it yourself.
|
||||||
query: string | Document,
|
}
|
||||||
rootValue?: any,
|
|
||||||
context?: any,
|
function runQuery(options: QueryOptions): Promise<GraphQLResult> {
|
||||||
variables?: { [key: string]: any },
|
|
||||||
operationName?: string,
|
|
||||||
//logFunction?: function => void
|
|
||||||
//validationRules?: No, too risky. If you want extra validation rules, then parse it yourself.
|
|
||||||
}): Promise<GraphQLResult> {
|
|
||||||
let documentAST: Document;
|
let documentAST: Document;
|
||||||
|
|
||||||
// if query is already an AST, don't parse or validate
|
// if query is already an AST, don't parse or validate
|
||||||
if (typeof query === 'string') {
|
if (typeof options.query === 'string') {
|
||||||
// parse
|
// parse
|
||||||
try {
|
try {
|
||||||
documentAST = parse(query);
|
documentAST = parse(options.query as string);
|
||||||
} catch (syntaxError) {
|
} catch (syntaxError) {
|
||||||
return Promise.resolve({ errors: [syntaxError] });
|
return Promise.resolve({ errors: [syntaxError] });
|
||||||
}
|
}
|
||||||
|
|
||||||
// validate
|
// validate
|
||||||
const validationErrors = validate(schema, documentAST);
|
const validationErrors = validate(options.schema, documentAST);
|
||||||
if (validationErrors.length) {
|
if (validationErrors.length) {
|
||||||
return Promise.resolve({ errors: validationErrors });
|
return Promise.resolve({ errors: validationErrors });
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
documentAST = query;
|
documentAST = options.query as Document;
|
||||||
}
|
}
|
||||||
|
|
||||||
// execute
|
// execute
|
||||||
return execute(
|
return execute(
|
||||||
schema,
|
options.schema,
|
||||||
documentAST,
|
documentAST,
|
||||||
rootValue,
|
options.rootValue,
|
||||||
context,
|
options.context,
|
||||||
variables,
|
options.variables,
|
||||||
operationName
|
options.operationName
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -1,3 +1,2 @@
|
||||||
import expressApollo from './integrations/expressApollo';
|
export { graphqlHTTP } from './integrations/expressApollo';
|
||||||
|
export { HapiApollo } from './integrations/hapiApollo';
|
||||||
export { expressApollo };
|
|
||||||
|
|
|
@ -11,7 +11,8 @@ import {
|
||||||
|
|
||||||
// TODO use import, not require... help appreciated.
|
// TODO use import, not require... help appreciated.
|
||||||
import * as express from 'express';
|
import * as express from 'express';
|
||||||
import request from 'supertest-as-promised';
|
// tslint:disable-next-line
|
||||||
|
const request = require('supertest-as-promised');
|
||||||
|
|
||||||
import { graphqlHTTP, ExpressApolloOptions, renderGraphiQL } from './expressApollo';
|
import { graphqlHTTP, ExpressApolloOptions, renderGraphiQL } from './expressApollo';
|
||||||
|
|
||||||
|
@ -52,9 +53,7 @@ describe('expressApollo', () => {
|
||||||
};
|
};
|
||||||
return request(app).get(
|
return request(app).get(
|
||||||
'/graphql?query={ testString }'
|
'/graphql?query={ testString }'
|
||||||
)
|
).then((res) => {
|
||||||
.expect(200)
|
|
||||||
.then((res) => {
|
|
||||||
return expect(res.body.data).to.deep.equal(expected);
|
return expect(res.body.data).to.deep.equal(expected);
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
|
@ -2,7 +2,7 @@ import * as express from 'express';
|
||||||
import * as graphql from 'graphql';
|
import * as graphql from 'graphql';
|
||||||
import { runQuery } from '../core/runQuery';
|
import { runQuery } from '../core/runQuery';
|
||||||
|
|
||||||
import { renderGraphiQL, GraphiQLData } from '../modules/renderGraphiQL';
|
import * as GraphiQL from '../modules/renderGraphiQL';
|
||||||
|
|
||||||
// TODO: will these be the same or different for other integrations?
|
// TODO: will these be the same or different for other integrations?
|
||||||
export interface ExpressApolloOptions {
|
export interface ExpressApolloOptions {
|
||||||
|
@ -15,7 +15,11 @@ export interface ExpressApolloOptions {
|
||||||
// answer: yes, it does. Func(req) => options
|
// answer: yes, it does. Func(req) => options
|
||||||
}
|
}
|
||||||
|
|
||||||
export function graphqlHTTP(options: ExpressApolloOptions) {
|
export interface ExpressHandler {
|
||||||
|
(req: express.Request, res: express.Response, next): void;
|
||||||
|
}
|
||||||
|
|
||||||
|
export function graphqlHTTP(options: ExpressApolloOptions): ExpressHandler {
|
||||||
if (!options) {
|
if (!options) {
|
||||||
throw new Error('Apollo graphqlHTTP middleware requires options.');
|
throw new Error('Apollo graphqlHTTP middleware requires options.');
|
||||||
}
|
}
|
||||||
|
@ -46,9 +50,9 @@ function getQueryString(req: express.Request): string {
|
||||||
|
|
||||||
// this returns the html for the GraphiQL interactive query UI
|
// 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.
|
// TODO: it's still missing a way to tell it where the GraphQL endpoint is.
|
||||||
export function renderGraphiQL(options: GraphiQLData) {
|
export function renderGraphiQL(options: GraphiQL.GraphiQLData) {
|
||||||
return (req: express.Request, res: express.Response, next) => {
|
return (req: express.Request, res: express.Response, next) => {
|
||||||
const graphiQLString = renderGraphiQL({
|
const graphiQLString = GraphiQL.renderGraphiQL({
|
||||||
query: options.query,
|
query: options.query,
|
||||||
variables: options.variables,
|
variables: options.variables,
|
||||||
operationName: options.operationName,
|
operationName: options.operationName,
|
||||||
|
|
52
src/integrations/hapiApollo.ts
Normal file
52
src/integrations/hapiApollo.ts
Normal file
|
@ -0,0 +1,52 @@
|
||||||
|
import * as hapi from 'hapi';
|
||||||
|
import * as graphql from 'graphql';
|
||||||
|
import { runQuery } from '../core/runQuery';
|
||||||
|
|
||||||
|
|
||||||
|
export interface IRegister {
|
||||||
|
(server: hapi.Server, options: any, next: any): void;
|
||||||
|
attributes?: any;
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface HapiApolloOptions {
|
||||||
|
schema: graphql.GraphQLSchema;
|
||||||
|
formatError?: Function;
|
||||||
|
rootValue?: any;
|
||||||
|
context?: any;
|
||||||
|
logFunction?: Function;
|
||||||
|
}
|
||||||
|
|
||||||
|
export class HapiApollo {
|
||||||
|
constructor() {
|
||||||
|
this.register.attributes = {
|
||||||
|
name: 'graphql',
|
||||||
|
version: '0.0.1',
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
public register: IRegister = (server: hapi.Server, options: HapiApolloOptions, next) => {
|
||||||
|
server.route({
|
||||||
|
method: 'GET',
|
||||||
|
path: '/test',
|
||||||
|
handler: (request, reply) => {
|
||||||
|
reply('test passed');
|
||||||
|
},
|
||||||
|
});
|
||||||
|
|
||||||
|
server.route({
|
||||||
|
method: 'POST',
|
||||||
|
path: '/',
|
||||||
|
handler: (request, reply) => {
|
||||||
|
return runQuery({
|
||||||
|
schema: options.schema,
|
||||||
|
query: request.payload,
|
||||||
|
}).then(gqlResponse => {
|
||||||
|
reply({ data: gqlResponse.data });
|
||||||
|
}).catch(errors => {
|
||||||
|
reply({ errors: errors }).code(500);
|
||||||
|
});
|
||||||
|
},
|
||||||
|
});
|
||||||
|
next();
|
||||||
|
}
|
||||||
|
}
|
|
@ -1,6 +1,6 @@
|
||||||
{
|
{
|
||||||
"compilerOptions": {
|
"compilerOptions": {
|
||||||
"target": "es5",
|
"target": "es6",
|
||||||
"module": "commonjs",
|
"module": "commonjs",
|
||||||
"moduleResolution": "node",
|
"moduleResolution": "node",
|
||||||
"sourceMap": true,
|
"sourceMap": true,
|
||||||
|
|
|
@ -4,18 +4,14 @@
|
||||||
"graphql": "github:nitintutlani/typed-graphql"
|
"graphql": "github:nitintutlani/typed-graphql"
|
||||||
},
|
},
|
||||||
"globalDependencies": {
|
"globalDependencies": {
|
||||||
"bluebird": "registry:dt/bluebird#2.0.0+20160319051630",
|
|
||||||
"body-parser": "registry:dt/body-parser#0.0.0+20160317120654",
|
"body-parser": "registry:dt/body-parser#0.0.0+20160317120654",
|
||||||
"es6-promise": "registry:dt/es6-promise#0.0.0+20160317120654",
|
|
||||||
"express": "registry:dt/express#4.0.0+20160317120654",
|
"express": "registry:dt/express#4.0.0+20160317120654",
|
||||||
"express-serve-static-core": "registry:dt/express-serve-static-core#0.0.0+20160322035842",
|
"express-serve-static-core": "registry:dt/express-serve-static-core#0.0.0+20160322035842",
|
||||||
"hapi": "registry:dt/hapi#13.0.0+20160521152637",
|
"hapi": "registry:dt/hapi#13.0.0+20160602125023",
|
||||||
"koa": "registry:dt/koa#2.0.0+20160317120654",
|
"koa": "registry:dt/koa#2.0.0+20160317120654",
|
||||||
"mime": "registry:dt/mime#0.0.0+20160316155526",
|
"mime": "registry:dt/mime#0.0.0+20160316155526",
|
||||||
"mocha": "registry:dt/mocha#2.2.5+20160317120654",
|
"mocha": "registry:dt/mocha#2.2.5+20160317120654",
|
||||||
"node": "registry:dt/node#6.0.0+20160524002506",
|
"node": "registry:dt/node#6.0.0+20160524002506",
|
||||||
"serve-static": "registry:dt/serve-static#0.0.0+20160501131543",
|
"serve-static": "registry:dt/serve-static#0.0.0+20160501131543"
|
||||||
"superagent": "registry:dt/superagent#1.4.0+20160317120654",
|
|
||||||
"supertest-as-promised": "registry:dt/supertest-as-promised#2.0.2+20160317120654"
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
Loading…
Add table
Reference in a new issue