Skip to content

Commit bf6485a

Browse files
whlsxlJasinYip
authored andcommitted
feat:pass other apollo server options. (#31)
1 parent d1cdb29 commit bf6485a

File tree

23 files changed

+361
-8
lines changed

23 files changed

+361
-8
lines changed

README.md

+18
Original file line numberDiff line numberDiff line change
@@ -67,6 +67,24 @@ exports.graphql = {
6767
onPreGraphQL: function* (ctx) {},
6868
// 开发工具 graphiQL 路由前的拦截器,建议用于做权限操作(如只提供开发者使用)
6969
onPreGraphiQL: function* (ctx) {},
70+
// apollo server的透传参数,参考[文档](https://www.apollographql.com/docs/apollo-server/api/apollo-server/#parameters)
71+
apolloServerOptions: {
72+
rootValue,
73+
formatError,
74+
formatResponse,
75+
mocks,
76+
schemaDirectives,
77+
introspection,
78+
playground,
79+
debug,
80+
validationRules,
81+
tracing,
82+
cacheControl,
83+
subscriptions,
84+
engine,
85+
persistedQueries,
86+
cors,
87+
}
7088
};
7189

7290
// 添加中间件拦截请求

app/middleware/graphql.js

+18-8
Original file line numberDiff line numberDiff line change
@@ -45,21 +45,31 @@ module.exports = (_, app) => {
4545
return async (ctx, next) => {
4646
/* istanbul ignore else */
4747
if (ctx.path === graphQLRouter) {
48+
const {
49+
onPreGraphiQL,
50+
onPreGraphQL,
51+
apolloServerOptions,
52+
} = options;
4853
if (ctx.request.accepts([ 'json', 'html' ]) === 'html' && graphiql) {
49-
if (options.onPreGraphiQL) {
50-
await options.onPreGraphiQL(ctx);
54+
if (onPreGraphiQL) {
55+
await onPreGraphiQL(ctx);
5156
}
5257
return graphiqlKoa({
5358
endpointURL: graphQLRouter,
5459
})(ctx);
5560
}
56-
if (options.onPreGraphQL) {
57-
await options.onPreGraphQL(ctx);
61+
if (onPreGraphQL) {
62+
await onPreGraphQL(ctx);
5863
}
59-
return graphqlKoa({
60-
schema: app.schema,
61-
context: ctx,
62-
})(ctx);
64+
const serverOptions = Object.assign(
65+
{},
66+
apolloServerOptions,
67+
{
68+
schema: app.schema,
69+
context: ctx,
70+
}
71+
);
72+
return graphqlKoa(serverOptions)(ctx);
6373
}
6474
await next();
6575
};
+35
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,35 @@
1+
'use strict';
2+
3+
const assert = require('assert');
4+
const mm = require('egg-mock');
5+
6+
describe('test/app/graphql-options.test.js', () => {
7+
let app;
8+
9+
before(() => {
10+
app = mm.app({
11+
baseDir: 'apps/graphql-options-app',
12+
});
13+
return app.ready();
14+
});
15+
16+
after(mm.restore);
17+
18+
it('should return custom error, use formatError', async () => {
19+
const resp = await app.httpRequest()
20+
.get('/graphql?query=query+getUser($id:Int){user(id:$id){name}}&variables={"id":1}')
21+
.expect(200);
22+
assert.equal(resp.body.errors[0].code, 100001);
23+
});
24+
25+
it('should return frameworks, user formatResponse', async () => {
26+
const resp = await app.httpRequest()
27+
.get('/graphql?query=query+getFramework($id:Int){framework(id:$id){name}}&variables={"id":1}')
28+
.expect(200);
29+
assert.deepEqual(resp.body.data, {
30+
frameworks: {
31+
name: 'framework1',
32+
},
33+
});
34+
});
35+
});
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
'use strict';
2+
3+
module.exports = {
4+
changedName: 'frameworks',
5+
};
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
'use strict';
2+
3+
module.exports = {
4+
upper(next) {
5+
return next().then(str => {
6+
if (typeof str === 'string') {
7+
return str.toUpperCase();
8+
}
9+
return str;
10+
});
11+
},
12+
};
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
directive @upper on FIELD_DEFINITION
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,30 @@
1+
'use strict';
2+
3+
const DataLoader = require('dataloader');
4+
5+
class FrameworkConnector {
6+
constructor(ctx) {
7+
this.ctx = ctx;
8+
this.loader = new DataLoader(this.fetch.bind(this));
9+
}
10+
11+
fetch(ids) {
12+
return Promise.resolve(ids.map(id => ({
13+
id,
14+
name: `framework${id}`,
15+
projects: [],
16+
})));
17+
}
18+
19+
fetchByIds(ids) {
20+
return this.loader.loadMany(ids);
21+
}
22+
23+
fetchById(id) {
24+
return this.loader.load(id);
25+
}
26+
27+
}
28+
29+
module.exports = FrameworkConnector;
30+
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
'use strict';
2+
3+
module.exports = {
4+
Query: {
5+
framework(root, { id }, ctx) {
6+
return ctx.connector.framework.fetchById(id);
7+
},
8+
},
9+
};
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
2+
type Framework {
3+
id: Int!
4+
name: String!
5+
projects: [Project]
6+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
'use strict';
2+
3+
module.exports = app => {
4+
return {
5+
Query: {
6+
projects() {
7+
console.log(app);
8+
return [];
9+
},
10+
},
11+
};
12+
};
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
2+
type Project {
3+
name: String!
4+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
directive @lowerCase on FIELD_DEFINITION
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
'use strict';
2+
3+
const { SchemaDirectiveVisitor } = require('graphql-tools');
4+
const { defaultFieldResolver } = require('graphql');
5+
6+
class LowerCaseDirective extends SchemaDirectiveVisitor {
7+
visitFieldDefinition(field) {
8+
const { resolve = defaultFieldResolver } = field;
9+
field.resolve = async function(...args) {
10+
let result = await resolve.apply(this, args);
11+
if (typeof result === 'string') {
12+
result = result.toLowerCase();
13+
}
14+
return result;
15+
};
16+
}
17+
}
18+
19+
module.exports = {
20+
lowerCase: LowerCaseDirective,
21+
};
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,38 @@
1+
'use strict';
2+
3+
const DataLoader = require('dataloader');
4+
5+
class UserConnector {
6+
constructor(ctx) {
7+
this.ctx = ctx;
8+
this.loader = new DataLoader(this.fetch.bind(this));
9+
}
10+
11+
fetch(ids) {
12+
// this.ctx.model.user.find(ids);
13+
return Promise.resolve(ids.map(id => ({
14+
id,
15+
name: `name${id}`,
16+
upperName: `name${id}`,
17+
lowerName: `name${id}`,
18+
password: `password${id}`,
19+
projects: [],
20+
})));
21+
}
22+
23+
fetchByIds(ids) {
24+
return this.loader.loadMany(ids);
25+
}
26+
27+
// eslint-disable-next-line no-unused-vars
28+
fetchById(id) {
29+
const err = new Error();
30+
err.code = 100001;
31+
throw err;
32+
// return this.loader.load(id);
33+
}
34+
35+
}
36+
37+
module.exports = UserConnector;
38+
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
'use strict';
2+
3+
module.exports = {
4+
Query: {
5+
user(root, { id }, ctx) {
6+
return ctx.connector.user.fetchById(id);
7+
},
8+
},
9+
};
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
type Query {
2+
user(id: Int): User
3+
projects: [Project!]
4+
framework(id: Int): Framework
5+
}
6+
7+
type User {
8+
id: String!
9+
password: String!
10+
name: String!
11+
upperName: String @upper
12+
lowerName: String @lowerCase
13+
projects: [Project!]
14+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
'use strict';
2+
3+
module.exports = () => {
4+
class Framework {
5+
find(ids) {
6+
return ids.map(id => ({
7+
id,
8+
name: `name${id}`,
9+
}));
10+
}
11+
}
12+
13+
return Framework;
14+
};
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
'use strict';
2+
3+
module.exports = () => {
4+
class User {
5+
find(ids) {
6+
return ids.map(id => ({
7+
id,
8+
name: `name${id}`,
9+
password: `password${id}`,
10+
}));
11+
}
12+
}
13+
14+
return User;
15+
};
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,25 @@
1+
'use strict';
2+
3+
module.exports = function(app) {
4+
app.get('/user', async ctx => {
5+
const req = {
6+
query: `{
7+
user(id: 2) {
8+
name
9+
}
10+
}`,
11+
};
12+
ctx.body = await ctx.graphql.query(JSON.stringify(req));
13+
});
14+
15+
app.get('/framework', async ctx => {
16+
const req = {
17+
query: `{
18+
framework(id: 2) {
19+
name
20+
}
21+
}`,
22+
};
23+
ctx.body = await ctx.graphql.query(JSON.stringify(req));
24+
});
25+
};
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
'use strict';
2+
3+
module.exports = app => {
4+
class FrameworkService extends app.Service {
5+
async getFrameworkList() {
6+
return [
7+
{ id: 1, name: 'framework1' },
8+
{ id: 2, name: 'framework2' },
9+
];
10+
}
11+
}
12+
return FrameworkService;
13+
};
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
'use strict';
2+
3+
module.exports = app => {
4+
class UserService extends app.Service {
5+
async getUserList() {
6+
return [
7+
{ id: '1', name: 'user1' },
8+
{ id: '2', name: 'user2' },
9+
];
10+
}
11+
}
12+
return UserService;
13+
};

0 commit comments

Comments
 (0)