• 设为首页
  • 点击收藏
  • 手机版
    手机扫一扫访问
    迪恩网络手机版
  • 关注官方公众号
    微信扫一扫关注
    迪恩网络公众号

join-monster/join-monster-graphql-tools-adapter: Use Join Monster to fetch your ...

原作者: [db:作者] 来自: 网络 收藏 邀请

开源软件名称(OpenSource Name):

join-monster/join-monster-graphql-tools-adapter

开源软件地址(OpenSource Url):

https://github.com/join-monster/join-monster-graphql-tools-adapter

开源编程语言(OpenSource Language):

JavaScript 100.0%

开源软件介绍(OpenSource Introduction):

Join Monster GraphQL Tools Adapter

Use Join Monster's SQL generation and query batching powers with the Apollo graphql-tools server package.

What's this package for?

Suppose you have a GraphQL schema for a forum website, defined with the Schema Language like so:

const typeDefs = `
type Comment {
  id: Int!,
  body: String!,
  postId: Int,
  authorId: Int,
  archived: Boolean
}

type Post {
  id: Int!,
  body: String!,
  authorId: Int,
  numComments: Int!,
  comments: [Comment]
}

type User {
  id: Int!,
  email: String!,
  fullName: String!,
  favNums: [Int],
  posts: [Post]
}

type Query {
  user(id: Int!): User
}
`

module.exports = typeDefs

When using graphql-js, the reference implementation, you tag the Type constructors with extra metadata to configure Join Monster. The schema language does not allow adding arbitrary properties to the type definitions.

This package let's you add those tags without messing with the internals of the built schema object. Once you familiarize yourself with Join Monster's API, you can use all the same properties by passing it to this function.

const joinMonsterAdapt = require('join-monster-graphql-tools-adapter')
const typeDefs = require('../path/to/types')

const joinMonster = require('join-monster').default
// node drivers for talking to SQLite
const db = require('sqlite')
const { makeExecutableSchema } = require('graphql-tools')

const resolvers = {
  Query: {
    // call joinMonster in the "user" resolver, and all child fields that are tagged with "sqlTable" are handled!
    user(parent, args, ctx, resolveInfo) {
      return joinMonster(resolveInfo, ctx, sql => {
        return db.all(sql)
      }, { dialect: 'sqlite3' })
    }
  },
  User: {
    // the only field that needs a resolver, joinMonster hydrates the rest!
    fullName(user) {
      return user.first_name + ' ' + user.last_name
    }
  }
}

const schema = makeExecutableSchema({
  typeDefs,
  resolvers
})

// tag the schema types with the extra join monster metadata
// Note the change in JoinMonster API (v3) - extensions: {} block
joinMonsterAdapt(schema, {
  Query: {
    fields: {
      // add a function to generate the "where condition"
      user: {
        extensions: {
          joinMonster: {
            where: (table, args) => `${table}.id = ${args.id}`
          }
        }
      }
    }
  },
  User: {
    // map the User object type to its SQL table
    extensions: {
      joinMonster: {
        sqlTable: 'accounts',
        uniqueKey: 'id',
      }
    },
    // tag the User's fields
    fields: {
      email: {
        extensions: {
          joinMonster: {
            sqlColumn: 'email_address'
          }
        }
      },
      fullName: {
        extensions: {
          joinMonster: {
            sqlDeps: [ 'first_name', 'last_name' ]
          }
        }
      },
      posts: {
        extensions: {
          joinMonster: {
            sqlJoin: (userTable, postTable) => `${userTable}.id = ${postTable}.author_id`,
          }
        }
      }
    }
  },
  Post: {
    extensions: {
      joinMonster: {
        sqlTable: 'posts',
        uniqueKey: 'id',
      }
    },
    fields: {
      numComments: {
        extensions: {
          joinMonster: {
        // count with a correlated subquery
            sqlExpr: table => `(SELECT count(*) FROM comments where ${table}.id = comments.post_id)`
          }
        }
      },
      comments: {
        // fetch the comments in another batch request instead of joining
        extensions: {
          joinMonster: {
            sqlBatch: {
              thisKey: 'post_id',
              parentKey: 'id'
            }
          }
        }
      }
    }
  },
  Comment: {
    extensions: {
      joinMonster: {
        sqlTable: 'comments',
        uniqueKey: 'id',
      }
    },
    fields: {
      postId: {
        extensions: {
          joinMonster: {
            sqlColumn: 'post_id'
            }
          }
      },
      authorId: {
        extensions: {
          joinMonster: {
            sqlColumn: 'author_id'
          }
        }
      }
    }
  }
})

Now that our schema is Join-monsterized, we are ready to start executing some queries!

const { graphql } = require('graphql')

const query = `{
  user(id: 1) {
    id
    fullName
    email
    posts {
      id
      body
      numComments
      comments {
        id
        body
        authorId
        archived
      }
    }
  }
}`
graphql(schema, query).then(doSomethingCrazy)

Advisory

There is a known issue (see #4) that passing the logger in graphql-tools makeExecutableSchema breaks automatic fetching of default column values. For the time being, it is suggested to remove the logger or add sqlColumn to every field.




鲜花

握手

雷人

路过

鸡蛋
该文章已有0人参与评论

请发表评论

全部评论

专题导读
上一篇:
nitintutlani/typed-graphql: Typescript type definitions for graphql [Not Active]发布时间:2022-06-22
下一篇:
Netflix/dgs-codegen发布时间:2022-06-22
热门推荐
阅读排行榜

扫描微信二维码

查看手机版网站

随时了解更新最新资讯

139-2527-9053

在线客服(服务时间 9:00~18:00)

在线QQ客服
地址:深圳市南山区西丽大学城创智工业园
电邮:jeky_zhao#qq.com
移动电话:139-2527-9053

Powered by 互联科技 X3.4© 2001-2213 极客世界.|Sitemap