cnpm install apollo-server-koa koa
const Koa = require('koa');
const {ApolloServer, gql} = require('apollo-server-koa'); // graphql-koa插件
const schema = require('./server/graphql/index.js'); //自定义的GraphQL的表
const server = new ApolloServer({ //创建Graphql server
schema,
resolvers: ({ ctx }) => {
// let token = ctx.
}
});
server.applyMiddleware({app}); //apollo server使用koa中间件
app.listen(9527, ()=> { //监听端口
console.log(`server running success at ${server.graphqlPath}`)
})
ApolloServe接受2个参数schema和context,schema是对查询字段类型的约束,resolvers是对查询到的数据进行过滤返回给前端。
schema官网原文解释:
// A schema is a collection of type definitions (hence "typeDefs")
// that together define the "shape" of queries that are executed against
// your data.
resolver官网原文解释:
// Resolvers define the technique for fetching the types defined in the
// schema. This resolver retrieves books from the "books" array above.
const resolvers = {
Query: {
books: () => books,
},
};
type Book {
title: String
author: Author
}
type Author {
name: String
books: [Book]
}
Int
: A signed 32‐bit integerFloat
: A signed double-precision floating-point valueString
: A UTF‐8 character sequenceBoolean
: true
or false
ID
(serialized as a String
): A unique identifier that's often used to refetch an object or as the key for a cache. Although it's serialized as a String
, an ID
is not intended to be human‐readable.其中ID是独一无二序列化后的字符串,通常用于缓存的key。
type Book {
title: String
author: Author
}
type Author {
name: String
books: [Book]
}
query UniversalQuery {
__typename
}
__typename预设属性不需要定义
query GetSearchResults {
search(contains: "Shakespeare") {
# Querying for __typename is almost always recommended,
# but it's even more important when querying a field that
# might return one of multiple types.
__typename
... on Book {
title
}
... on Author {
name
}
}
}
{
"data": {
"search": [
{
"__typename": "Book",
"title": "The Complete Works of William Shakespeare"
},
{
"__typename": "Author",
"name": "William Shakespeare"
}
]
}
}
type Query {
books: [Book]
authors: [Author]
}
The Query
type is a special object type that defines all of the top-level entry points for queries that clients execute against your server.
This Query
type defines two fields: books
and authors
. Each field returns a list of the corresponding type.(e.g., /api/books
and /api/authors
)
query定义读类型,mutation定义写类型。
type Mutation {
addBook(title: String, author: String): Book
}
定义新增一个book对象,参数和返回值符合Schema Basics中的book type。
Like queries, mutations match the structure of your schema's type definitions. The following mutation creates a new Book
and requests certain fields of the created object as a return value:
mutation CreateBook {
addBook(title: "Fox in Socks", author: "Dr. Seuss") {
title
author {
name
}
}
}
查询新增值与response返回结果一致
{
"data": {
"addBook": {
"title": "Fox in Socks",
"author": {
"name": "Dr. Seuss"
}
}
}
}
订阅推送类型。
输入类型是一种特殊的对象类型,它允许您将分层数据作为字段的参数提供(而不是仅提供平面标量参数)。
input BlogPostContent {
title: String
body: String
}
type Mutation {
createBlogPost(content: BlogPostContent!): Post
updateBlogPost(id: ID!, content: BlogPostContent!): Post
}
enum AllowedColor {
RED
GREEN
BLUE
}
type Query {
favoriteColor: AllowedColor # enum return value
avatar(borderColor: AllowedColor): String # enum argument
}
union Media = Book | Movie
"Description for the type"
type MyObjectType {
"""
Description for field
Supports **multi-line** description for your [API](http://example.com)!
"""
myField: String!
otherField(
"Description for argument"
arg: Int
)
}
""" xxx """ 多行注释
" xxx " 单行注释
定义resolver 返回值类型
const resolvers = {
SearchResult: {
__resolveType(obj, context, info){
// Only Author has a name field
if(obj.name){
return 'Author';
}
// Only Book has a title field
if(obj.title){
return 'Book';
}
return null; // GraphQLError is thrown
},
},
Query: {
search: () => { ... }
},
};
自定义标量:
const { GraphQLScalarType, Kind } = require('graphql');
const dateScalar = new GraphQLScalarType({
name: 'Date',
description: 'Date custom scalar type',
serialize(value) {
return value.getTime(); // Convert outgoing Date to integer for JSON
},
parseValue(value) {
return new Date(value); // Convert incoming integer to Date
},
parseLiteral(ast) {
if (ast.kind === Kind.INT) {
return new Date(parseInt(ast.value, 10)); // Convert hard-coded AST string to integer and then to Date
}
return null; // Invalid hard-coded value (not an integer)
},
});
parseLiteral
When an incoming query string includes the scalar as a hard-coded argument value, that value is part of the query document's abstract syntax tree (AST). Apollo Server calls the parseLiteral
method to convert the value's AST representation to the scalar's back-end representation.
In the example above, parseLiteral
converts the AST value from a string to an integer, and then converts from integer to Date
to match the result of parseValue
.
type ExampleType {
oldField: String @deprecated(reason: "Use `newField`.") newField: String
}
弃用指令
The GraphQL specification defines the following default directives:
DIRECTIVE | DESCRIPTION |
---|---|
@deprecated(reason: String) | Marks the schema definition of a field or enum value as deprecated with an optional reason. |
@skip(if: Boolean!) | If true , the decorated field or fragment in an operation is not resolved by the GraphQL server. |
@include(if: Boolean!) | If false , the decorated field or fragment in an operation is not resolved by the GraphQL server. |
解析器被传递4个参数,分别是:
在构造函数初始化context函数,所有解析器都会调用这个函数。上下文初始化可以是异步函数。
// Constructor
const server = new ApolloServer({
typeDefs,
resolvers,
context: ({ req }) => ({
authScope: getScope(req.headers.authorization)
})
}));
// Example resolver
(parent, args, context, info) => {
if(context.authScope !== ADMIN) throw new AuthenticationError('not admin');
// Proceed
}
null
/ undefined