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

feat:pass other apollo server options. #31

Merged
merged 1 commit into from
Oct 31, 2019
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
18 changes: 18 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -67,6 +67,24 @@ exports.graphql = {
onPreGraphQL: function* (ctx) {},
// 开发工具 graphiQL 路由前的拦截器,建议用于做权限操作(如只提供开发者使用)
onPreGraphiQL: function* (ctx) {},
// apollo server的透传参数,参考[文档](https://www.apollographql.com/docs/apollo-server/api/apollo-server/#parameters)
apolloServerOptions: {
rootValue,
formatError,
formatResponse,
mocks,
schemaDirectives,
introspection,
playground,
debug,
validationRules,
tracing,
cacheControl,
subscriptions,
engine,
persistedQueries,
cors,
}
};

// 添加中间件拦截请求
Expand Down
26 changes: 18 additions & 8 deletions app/middleware/graphql.js
Original file line number Diff line number Diff line change
Expand Up @@ -45,21 +45,31 @@ module.exports = (_, app) => {
return async (ctx, next) => {
/* istanbul ignore else */
if (ctx.path === graphQLRouter) {
const {
onPreGraphiQL,
onPreGraphQL,
apolloServerOptions,
} = options;
if (ctx.request.accepts([ 'json', 'html' ]) === 'html' && graphiql) {
if (options.onPreGraphiQL) {
await options.onPreGraphiQL(ctx);
if (onPreGraphiQL) {
await onPreGraphiQL(ctx);
}
return graphiqlKoa({
endpointURL: graphQLRouter,
})(ctx);
}
if (options.onPreGraphQL) {
await options.onPreGraphQL(ctx);
if (onPreGraphQL) {
await onPreGraphQL(ctx);
}
return graphqlKoa({
schema: app.schema,
context: ctx,
})(ctx);
const serverOptions = Object.assign(
{},
apolloServerOptions,
{
schema: app.schema,
context: ctx,
}
);
return graphqlKoa(serverOptions)(ctx);
}
await next();
};
Expand Down
35 changes: 35 additions & 0 deletions test/app/graphql-options/graphql.test.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
'use strict';

const assert = require('assert');
const mm = require('egg-mock');

describe('test/app/graphql-options.test.js', () => {
let app;

before(() => {
app = mm.app({
baseDir: 'apps/graphql-options-app',
});
return app.ready();
});

after(mm.restore);

it('should return custom error, use formatError', async () => {
const resp = await app.httpRequest()
.get('/graphql?query=query+getUser($id:Int){user(id:$id){name}}&variables={"id":1}')
.expect(200);
assert.equal(resp.body.errors[0].code, 100001);
});

it('should return frameworks, user formatResponse', async () => {
const resp = await app.httpRequest()
.get('/graphql?query=query+getFramework($id:Int){framework(id:$id){name}}&variables={"id":1}')
.expect(200);
assert.deepEqual(resp.body.data, {
frameworks: {
name: 'framework1',
},
});
});
});
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
'use strict';

module.exports = {
changedName: 'frameworks',
};
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
'use strict';

module.exports = {
upper(next) {
return next().then(str => {
if (typeof str === 'string') {
return str.toUpperCase();
}
return str;
});
},
};
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
directive @upper on FIELD_DEFINITION
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
'use strict';

const DataLoader = require('dataloader');

class FrameworkConnector {
constructor(ctx) {
this.ctx = ctx;
this.loader = new DataLoader(this.fetch.bind(this));
}

fetch(ids) {
return Promise.resolve(ids.map(id => ({
id,
name: `framework${id}`,
projects: [],
})));
}

fetchByIds(ids) {
return this.loader.loadMany(ids);
}

fetchById(id) {
return this.loader.load(id);
}

}

module.exports = FrameworkConnector;

Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
'use strict';

module.exports = {
Query: {
framework(root, { id }, ctx) {
return ctx.connector.framework.fetchById(id);
},
},
};
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@

type Framework {
id: Int!
name: String!
projects: [Project]
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
'use strict';

module.exports = app => {
return {
Query: {
projects() {
console.log(app);
return [];
},
},
};
};
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@

type Project {
name: String!
}
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
directive @lowerCase on FIELD_DEFINITION
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
'use strict';

const { SchemaDirectiveVisitor } = require('graphql-tools');
const { defaultFieldResolver } = require('graphql');

class LowerCaseDirective extends SchemaDirectiveVisitor {
visitFieldDefinition(field) {
const { resolve = defaultFieldResolver } = field;
field.resolve = async function(...args) {
let result = await resolve.apply(this, args);
if (typeof result === 'string') {
result = result.toLowerCase();
}
return result;
};
}
}

module.exports = {
lowerCase: LowerCaseDirective,
};
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
'use strict';

const DataLoader = require('dataloader');

class UserConnector {
constructor(ctx) {
this.ctx = ctx;
this.loader = new DataLoader(this.fetch.bind(this));
}

fetch(ids) {
// this.ctx.model.user.find(ids);
return Promise.resolve(ids.map(id => ({
id,
name: `name${id}`,
upperName: `name${id}`,
lowerName: `name${id}`,
password: `password${id}`,
projects: [],
})));
}

fetchByIds(ids) {
return this.loader.loadMany(ids);
}

// eslint-disable-next-line no-unused-vars
fetchById(id) {
const err = new Error();
err.code = 100001;
throw err;
// return this.loader.load(id);
}

}

module.exports = UserConnector;

Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
'use strict';

module.exports = {
Query: {
user(root, { id }, ctx) {
return ctx.connector.user.fetchById(id);
},
},
};
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
type Query {
user(id: Int): User
projects: [Project!]
framework(id: Int): Framework
}

type User {
id: String!
password: String!
name: String!
upperName: String @upper
lowerName: String @lowerCase
projects: [Project!]
}
14 changes: 14 additions & 0 deletions test/fixtures/apps/graphql-options-app/app/model/framework.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
'use strict';

module.exports = () => {
class Framework {
find(ids) {
return ids.map(id => ({
id,
name: `name${id}`,
}));
}
}

return Framework;
};
15 changes: 15 additions & 0 deletions test/fixtures/apps/graphql-options-app/app/model/user.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
'use strict';

module.exports = () => {
class User {
find(ids) {
return ids.map(id => ({
id,
name: `name${id}`,
password: `password${id}`,
}));
}
}

return User;
};
25 changes: 25 additions & 0 deletions test/fixtures/apps/graphql-options-app/app/router.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
'use strict';

module.exports = function(app) {
app.get('/user', async ctx => {
const req = {
query: `{
user(id: 2) {
name
}
}`,
};
ctx.body = await ctx.graphql.query(JSON.stringify(req));
});

app.get('/framework', async ctx => {
const req = {
query: `{
framework(id: 2) {
name
}
}`,
};
ctx.body = await ctx.graphql.query(JSON.stringify(req));
});
};
13 changes: 13 additions & 0 deletions test/fixtures/apps/graphql-options-app/app/service/framework.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
'use strict';

module.exports = app => {
class FrameworkService extends app.Service {
async getFrameworkList() {
return [
{ id: 1, name: 'framework1' },
{ id: 2, name: 'framework2' },
];
}
}
return FrameworkService;
};
13 changes: 13 additions & 0 deletions test/fixtures/apps/graphql-options-app/app/service/user.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
'use strict';

module.exports = app => {
class UserService extends app.Service {
async getUserList() {
return [
{ id: '1', name: 'user1' },
{ id: '2', name: 'user2' },
];
}
}
return UserService;
};
Loading