sofa graphql 2 rest api 试用
Posted rongfengliang-荣锋亮
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了sofa graphql 2 rest api 试用相关的知识,希望对你有一定的参考价值。
大部分代码还是来自sofa 的官方文档,同时添加了docker && docker-compose集成
备注: 代码使用typescript 同时运行的时候为了方便直接运行使用ts-node 运行
环境准备
- docker-compose 文件
version: "3"
services:
api:
build: ./
image: dalongrong/sofa-graphql2rest
ports:
- "4000:4000"
- dockerfile
FROM node:alpine
WORKDIR /server
COPY . /server
RUN yarn install
CMD ["yarn", "start"]
代码说明
- package.json 依赖包
{
"name": "sofa-graphql2rest",
"version": "1.0.0",
"license": "MIT",
"main": "server.js",
"scripts": {
"start": "ts-node index.ts"
},
"dependencies": {
"body-parser": "1.18.3",
"chalk": "2.4.2",
"express": "4.16.4",
"express-graphql": "0.7.1",
"graphql": "^14.0.2",
"graphql-subscriptions": "^1.0.0",
"graphql-tag": "2.10.0",
"graphql-tools": "4.0.3",
"sofa-api": "^0.2.2",
"swagger-ui-express": "4.0.2"
},
"devDependencies": {
"@types/swagger-ui-express": "3.0.0",
"@types/body-parser": "1.17.0",
"@types/express": "4.16.0",
"@types/express-graphql": "0.6.2",
"@types/graphql": "14.0.3",
"esm": "^3.0.84",
"ts-loader": "^5.3.3",
"ts-node": "7.0.1",
"typescript": "3.2.2"
}
}
- graphql api 开发
基于graphql-tools,同时集成express-graphql 以及swagger open api 文档
graphql schema 定义 type.ts
import gql from \'graphql-tag\';
export const typeDefs = gql`
type Pizza {
dough: String!
toppings: [String!]
}
type Salad {
ingredients: [String!]!
}
union Food = Pizza | Salad
type Book {
id: ID!
title: String!
}
type User {
id: ID!
name: String!
favoritePizza: Pizza!
favoriteBook: Book!
favoriteFood: Food!
shelf: [Book!]!
}
type Post {
comments(filter: String!): [String!]
}
type Query {
me: User
user(id: ID!): User
users: [User!]
usersLimit(limit: Int!): [User!]
usersSort(sort: Boolean!): [User!]
book(id: ID!): Book
books: [Book!]
never: String
feed: [Post]
}
type Mutation {
addBook(title: String!): Book
}
type Subscription {
onBook: Book
}
schema {
query: Query
mutation: Mutation
subscription: Subscription
}
`;
resolvers 定义 resolvers.ts 同时集成了subscription
import { PubSub } from \'graphql-subscriptions\';
const pubsub = new PubSub();
import {
UsersCollection,
BooksCollection,
PostsCollection,
} from \'./collections\';
const BOOK_ADDED = \'BOOK_ADDED\';
export const resolvers: any = {
Query: {
me() {
return UsersCollection.get(1);
},
user(_: any, { id }: any) {
return UsersCollection.get(id);
},
users() {
return UsersCollection.all();
},
usersLimit(_: any, { limit }: any) {
return UsersCollection.all().slice(0, limit);
},
usersSort(_: any, { sort }: any) {
const users = UsersCollection.all();
return sort ? users.sort((a, b) => b.id - a.id) : users;
},
book(_: any, { id }: any) {
return BooksCollection.get(id);
},
books() {
return BooksCollection.all();
},
feed() {
return PostsCollection.all();
},
},
Mutation: {
addBook(_: any, { title }: any) {
const book = BooksCollection.add(title);
pubsub.publish(BOOK_ADDED, { onBook: book });
return book;
},
},
Subscription: {
onBook: {
subscribe: () => pubsub.asyncIterator([BOOK_ADDED]),
},
},
Food: {
__resolveType(obj: any) {
if (obj.ingredients) {
return \'Salad\';
}
if (obj.toppings) {
return \'Pizza\';
}
return null;
},
},
Post: {
comments(post: { comments: string[] }, { filter }: { filter: string }) {
return post.comments.filter(
comment =>
!filter || comment.toLowerCase().indexOf(filter.toLowerCase()) > -1
);
},
},
};
代码入口
index.ts
import * as express from \'express\';
import { makeExecutableSchema } from \'graphql-tools\';
import * as bodyParser from \'body-parser\';
import * as useGraphQL from \'express-graphql\';
import * as swaggerUi from \'swagger-ui-express\';
import chalk from \'chalk\';
import { resolve } from \'path\';
import { typeDefs } from \'./types\';
import { resolvers } from \'./resolvers\';
import * as swaggerDocument from \'./swagger.json\';
// Sofa
import sofa, { OpenAPI } from \'sofa-api\';
import { logger } from \'sofa-api/dist/logger\';
const app = express();
app.use(bodyParser.json());
const schema = makeExecutableSchema({
typeDefs,
resolvers: resolvers as any,
});
const openApi = OpenAPI({
schema,
info: {
title: \'Example API\',
version: \'3.0.0\',
},
});
app.use(
sofa({
schema,
ignore: [\'User.favoriteBook\'],
onRoute(info) {
openApi.addRoute(info, {
basePath: \'\',
});
},
})
);
openApi.save(resolve(__dirname, \'./swagger.json\'));
app.use(\'/docs\', swaggerUi.serve, swaggerUi.setup(swaggerDocument));
app.use(\'/webhook\', (req, res) => {
logger.info(\'Received a webhook\', req.body);
res.statusCode = 200;
res.statusMessage = \'OK\';
res.send();
});
app.use(
\'/graphql\',
useGraphQL({
schema,
graphiql: true,
})
);
const port = 4000;
app.listen(port, () => {
const url = `http://localhost:${4000}`;
function printUrl(path: string) {
return chalk.gray(url + path);
}
console.log(`
${chalk.bold(\'GraphQL:\')} ${printUrl(\'/graphql\')}
${chalk.bold(\'Queries:\')}
me: ${printUrl(\'/me\')}
users: ${printUrl(\'/users\')}
user: ${printUrl(\'/user/1\')}
books: ${printUrl(\'/books\')}
book: ${printUrl(\'/book/1\')}
${chalk.bold(\'Mutations:\')}
addBook: ${printUrl(\'/add-book\')} ${chalk.italic.gray(
\'POST: {title}\'
)}
`);
});
运行&&测试
- 运行
docker-compose build && docker-compose up -d
- 效果
openapi docs
http://localhost:4000/docs
graphql ui graphiql 工具
http://localhost:4000/graphql
- 查询执行
rest api
graphql api
说明
sofa 在设计上充分graphql 的ast 语法,同时集成了open api ,同时按照设计的方案,可以集成比较多的graphql 的平台,主要是scema
参考资料
https://github.com/rongfengliang/sofa-graphql2rest-docker-compose
https://sofa-api.com/
https://github.com/Urigo/sofa
以上是关于sofa graphql 2 rest api 试用的主要内容,如果未能解决你的问题,请参考以下文章
使用 REST 包装 GraphQL 从 NestJS 提供 GraphQL 和 REST API