项目作者: redux-model

项目描述 :
Generator graphql for TypeScript
高级语言: TypeScript
项目地址: git://github.com/redux-model/graphql.git
创建时间: 2020-09-13T12:50:03Z
项目社区:https://github.com/redux-model/graphql

开源协议:MIT License

下载


redux-model-graphql

Graphql模板运行时工具,自动生成标准模板和Typescript类型, 配合Redux-Model实现graphql请求。

License
GitHub Workflow Status (branch)
Codecov

特性

  • 只需写一次,Graphql语法和Typescript同时拥有
  • 自动收集参数
  • 自动识别参数基础类型
  • 单一职责,只生成标准graphql字符串
  • 支持所有graphql语法

安装

  1. yarn add @redux-model/graphql

基础用法

  1. import { Model } from '@redux-model/react';
  2. import { types, graphql } from '@redux-model/graphql';
  3. const getUserTpl = graphql.query({
  4. getUser: {
  5. id: types.number, // number
  6. name: types.string, // string
  7. bankAccount: { // object
  8. id: types.number,
  9. branch: types.string.number, // string | number
  10. },
  11. }
  12. });
  13. // console.log(getUserTpl.toString());
  14. // 生成模板:
  15. // query GetUser {
  16. // getUser {
  17. // id
  18. // name
  19. // bankAccount {
  20. // id
  21. // branch
  22. // }
  23. // }
  24. // }
  25. type Response = {
  26. data: typeof getUserTpl.type;
  27. };
  28. interface Data {
  29. list?: Response['data'];
  30. };
  31. class TestModel extends Model<Data> {
  32. getUser = $api.action(() => {
  33. return this
  34. .post<Response>('/graphql')
  35. .graphql(getUserTpl)
  36. .onSuccess((state, action) => {
  37. state.list = action.response.data;
  38. });
  39. });
  40. protected initialState(): Data {
  41. return {};
  42. }
  43. }

函数

  1. const tpl = graphql.query({
  2. getUser: {
  3. id: types.number,
  4. logs: types.fn(['page: Int!', 'pageSize as size: Int'], types.array({
  5. id: types.number,
  6. title: types.string,
  7. })),
  8. }
  9. });
  10. // 生成模板:
  11. // query GetUser ($page: Int!, $size: Int) {
  12. // getUser: {
  13. // id
  14. // logs (page: $page, pageSize: $size) {
  15. // id
  16. // title
  17. // }
  18. // }
  19. // }
  20. // 在模型中使用
  21. type Response = {
  22. data: typeof tpl.type;
  23. };
  24. type Data = Response['data'];
  25. class TestModel extends Model<Data> {
  26. getUser = $api.action((page: number, size: number = 10) => {
  27. return this
  28. .post<Response>('/graphql')
  29. .graphql(tpl({
  30. page,
  31. size,
  32. }))
  33. .onSuccess((state, action) => {
  34. return action.response.data;
  35. });
  36. });
  37. protected initialState(): Data {
  38. return {};
  39. }
  40. }

片段

  1. const fragment1 = graphql.fragment('User', {
  2. name: types.string,
  3. });
  4. const tpl = graphql.query({
  5. getUser: {
  6. id: types.number,
  7. ...fragment1,
  8. }
  9. });
  10. // 生成模板:
  11. // query GetUser {
  12. // getUser: {
  13. // id
  14. // ...UserFragment
  15. // }
  16. // }
  17. //
  18. // fragment UserFragment on User {
  19. // name
  20. // }

内联片段

  1. const tpl = graphql.query({
  2. getUser: {
  3. id: types.number,
  4. ...types.on('User', {
  5. name: types.string,
  6. }),
  7. ...types.on(['Hero', 'Thief'], {
  8. age: types.number,
  9. }),
  10. }
  11. });
  12. // 生成模板:
  13. // query GetUser {
  14. // getUser: {
  15. // id
  16. // ... on User {
  17. // name
  18. // }
  19. // ... on Hero {
  20. // age
  21. // }
  22. // ... on Thief {
  23. // age
  24. // }
  25. // }
  26. // }

互斥内联片段

生成的模板和内联片段一样,但是在类型上是互斥的

  1. const tpl = graphql.query({
  2. getUser: {
  3. id: types.number,
  4. ...types.union(
  5. types.on('User', {
  6. kind: types.custom<'User'>(),
  7. name: types.string,
  8. age: types.number,
  9. }),
  10. types.on('Admin', {
  11. kind: types.custom<'Admin'>(),
  12. name1: types.string,
  13. age1: types.number,
  14. }),
  15. )
  16. }
  17. });
  18. // 生成模板:
  19. // query GetUser {
  20. // getUser: {
  21. // id
  22. // ... on User {
  23. // kind
  24. // name
  25. // age
  26. // }
  27. // ... on Admin {
  28. // kind
  29. // name1
  30. // age1
  31. // }
  32. // }
  33. // }

您可以通过判断来确定哪个字段存在

  1. if (getUser.kind === 'User') {
  2. // getUser.name
  3. // getUser.age
  4. } else if (getUser.kind === 'Admin') {
  5. // getUser.name1
  6. // getUser.age1
  7. }
  8. if ('age' in getUser) {
  9. // getUser.name
  10. // getUser.age
  11. } else if ('age1' in getUser) {
  12. // getUser.name1
  13. // getUser.age1
  14. }

⚠️注意:互斥内联片段中互斥的字段无法收集函数参数名

指令

  1. const tpl = graphql.query({
  2. getUser: {
  3. id: types.number.include('test: Boolean'), // number | undefined
  4. logs: types.skip('other: Boolean').object({ // object | undefined
  5. id: types.number,
  6. title: types.string,
  7. }),
  8. }
  9. });
  10. // 生成模板:
  11. // query GetUser ($test: Boolean, $other: Boolean) {
  12. // getUser: {
  13. // id @include(if: $test)
  14. // logs @skip(if: $other) {
  15. // id
  16. // title
  17. // }
  18. // }
  19. // }