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

harbor rest api 转graphql api

资讯 | GraphQL vs REST API 世纪Battle

GraphQL vs REST API 架构,谁更胜一筹?

GraphQL 与 REST API

使用 GraphQL 封装 REST API / 仅使用 GraphQL