egg-apollo-server-graphql
    TypeScript icon, indicating that this package has built-in type declarations

    1.0.3 • Public • Published

    egg-apollo-server

    NPM version Test coverage npm download Last commit License

    The apollo-server-koa plugin in egg.

    Getting Started

    install

    With yarn:

    yarn add egg-apollo-server-graphql

    or using npm

    npm install --save egg-apollo-server-graphql

    Usage

    1. 开启插件
    // config/plugin.js
    exports.graphql= {
        enable: true,
        package: 'egg-apollo-server-graphql',
      },
    1. 在 config/config.${env}.js 配置 graphql options。支持 apollo-server 中的所有 options.
    config.graphql = {
      router: '/graphql',
      app: true, //是否加载到 app 上,默认为 true
      agent: false, //是否加载到 agent 上,默认为 false
      graphiql: true, //是否加载开发者工具 playground,默认为 true
      uploads: true, //是否开启文件上传功能,默认开启
     
      //是否添加默认的type Query,Mutation,默认为true
      //如果为true须使用extend type Query|extend type Mutation,因为graphql规定同一个type只能定义一个
      //带来的好处时egg/graphql下不用再新建query,mutation目录
      defaultEmptySchema: true,
     
      //subscriptions的值为<Object>|<String>|false 见https://www.apollographql.com/docs/apollo-server/api/apollo-server/
      //如果为String 表示订阅的路径
      //如果为false 关闭订阅
      //如果为object 可以添加path,keepAlive,onConnect,onDisconnect
      subscriptions: {
        onConnect: (connectionParams, webSocket) => {
          console.log('connect');
          if (connectionParams.authToken) {
            // return validateToken(connectionParams.authToken)
            //   .then(findUser(connectionParams.authToken))
            //   .then(user => {
            //     return {
            //       currentUser: user,
            //     }
            //   })
          }
     
          // throw new Error('Missing auth token!')
        }
      },
      //可选字段,接受项目中发生的错误,然后自定义错误返回给前端
      formatError: (error, app) => {
        // console.log(error);
        app.logger.error(error);
        return error;
      },
      debug: false // 发生错误时,是否包含错误堆栈信息,生产环境要设置为false
    };
     
    // 添加中间件拦截请求
    exports.middleware = ['graphql'];
    1. 项目目录

    在 app 目录下新建 graphql 目录, graphql 相关文件写在此目录,插件会读取 app/graphql 下所有目录里面的 graphql 相关文件

    ├── app
    │   ├── controller
    │   │   └── home.js
    │   ├── graphql
    │   │   ├── tag
    │   │   │   ├── resolver.js
    │   │   │   └── schema.graphql
    │   │   └── user
    │   │       ├── resolver.js
    │   │       └── schema.graphql
    │   ├── router.js
    │   └── service
    ├── config
    │   ├── config.default.js
    │   └── plugin.js
    ├── package.json
    └── package-lock.json
    

    graphql 相关文件包含:

    • schema.graphql
      a GraphQL type language string
    #插件设置了默认的Query,Mutation 所以不用定义Query,直接使用extend继承
    extend type Query {
      users: [User]
      user(id: ID!): User
    }
    type User {
      id: ID!
      name: String
      age: Int
    }
     
    extend type Mutation {
      addUser(input: AddUser): User
      updateUser(input: UpdateUser): User
      deleteUser(id: ID!): Boolean
    }
    input AddUser {
      name: String
      age: Int
    }
    input UpdateUser {
      id: ID!
      name: String
      age: Int
    }
    • resolver.js
      a nested object that maps type and field names to resolver functions
    module.exports = {
      Query: {
        users: () => {
          return users;
        },
        user: (root, params) => {
          const { id } = params;
          return users.find(user => user.id == id);
        }
      }
    };
    • schemaDirective.js
      a nested object that maps type and field names to resolver functions
    const { defaultFieldResolver } = require('graphql');
    const { SchemaDirectiveVisitor } = require('graphql-tools');
    class UpperDirective extends SchemaDirectiveVisitor {
      visitFieldDefinition(field) {
        const { resolve = defaultFieldResolver } = field;
        field.resolve = async (...args) => {
          const defaultText = await resolve.apply(this, args);
          if (typeof defaultText === 'string') {
            return defaultText.toUpperCase();
          }
          return defaultText;
        };
      }
    }
    module.exports = {
      upper: UpperDirective
    };

    demo

    egg 中使用 graphql

    options

    • router - 处理 graphql 请求的路由,默认为 "/graphql"
    • app - 是否加载到 app 上,默认为 true
    • agent - 是否加载到 agent 上,默认为 false
    • graphiql - 是否加载开发者工具 playground,默认为 true
    • uploads - 是否开启文件上传功能,默认为 true

    其它 options 参 见apollo-server

    egg-apollo-server 和 egg-graphql 的区别

    1. 不支持 onPreGraphQL,onPreGraphiQL
    2. 不支持 directiveResolvers,用 schemaDirective 替代
    3. 支持文件上传.
    4. 更漂亮的调试界面.
    5. 支持自定义错误类型
    6. 支持 dataSources
    7. 支持缓存(redis 等)
    8. 支持 Subscriptions
    9. 支持 mock
    10. 支持默认的 Query

    设置默认 Query 的好处?

    未设置默认 Query 之前,假如有 user,tag 两个表,需要建四个文件夹,这样导致 mutation,query 包含了所有的一级查询,增加,更新,删除 而 user 相关定义又在 user/graphql 下

    app
    └── graphql
        ├── mutation
        │   └── schema.graphql
        ├── query
        │   └── schema.graphql
        ├── tag
        │   ├── resolver.js
        │   └── schema.graphql
        └── user
            ├── resolver.js
            └── schema.graphql
    

    有了默认 Query 后,只需要建两个文件夹

    app
    └── graphql
        ├── tag
        │   ├── resolver.js
        │   └── schema.graphql
        └── user
            ├── resolver.js
            └── schema.graphql
    

    只需要在各自 schema.graphql 定义 例如 egg 中使用 graphql

    #app/graphql/user/schema.graphql
    extend type Query {
      user(id: ID!): User
    }
    extend type Mutation {
      addUser(input: AddUser): User
    }
    input AddUser {
      name: String
      age: Int
    }
    type User {
      id: ID!
      name: String
      age: Int
    }

    TODO

    • 支持自定义 schema,可自定义 graphql 相关文件结构
    • 支持 typeDefs 里引用 model 数据

    Install

    npm i egg-apollo-server-graphql

    DownloadsWeekly Downloads

    14

    Version

    1.0.3

    License

    MIT

    Unpacked Size

    44.7 kB

    Total Files

    49

    Last publish

    Collaborators

    • buzhibujue