14 个重大版本

0.14.0 2024 年 3 月 26 日
0.13.0 2023 年 5 月 30 日
0.12.0 2023 年 1 月 12 日
0.11.0 2022 年 6 月 21 日
0.3.0 2018 年 7 月 24 日

#6 in HTTP 客户端

Download history 89613/week @ 2024-04-26 90861/week @ 2024-05-03 103762/week @ 2024-05-10 109434/week @ 2024-05-17 114848/week @ 2024-05-24 126334/week @ 2024-05-31 125815/week @ 2024-06-07 106264/week @ 2024-06-14 110195/week @ 2024-06-21 106471/week @ 2024-06-28 110128/week @ 2024-07-05 114354/week @ 2024-07-12 112041/week @ 2024-07-19 115476/week @ 2024-07-26 108370/week @ 2024-08-02 111330/week @ 2024-08-09

469,371 个月下载量
用于 111 Crates(90 个直接使用)

Apache-2.0 OR MIT

35KB
235

graphql_client

Github actions Status docs crates.io

Rust 的类型化 GraphQL 客户端库。

特性

  • 查询变量和响应的精确类型。
  • 支持 GraphQL 片段、对象、联合、输入、枚举、自定义标量和输入对象。
  • 在浏览器(WebAssembly)中运行。
  • 订阅支持(目前仅支持序列化和反序列化)。
  • 从 GraphQL 模式复制文档到生成的 Rust 代码。
  • 对生成的响应支持任意 derive。
  • 支持任意自定义标量。
  • 支持查询文档中每个查询多个操作。
  • 支持将 GraphQL 字段设置为已弃用,并由 Rust 编译器检查其使用。
  • 可选的基于 reqwest 的客户端,用于从浏览器进行无样板 API 调用。
  • 显式和隐式空支持。

入门指南

  • 如果您不熟悉 GraphQL,官方网站 https://graphql.net.cn/ 提供了非常好的全面介绍。

  • 一旦您编写了查询(很可能是使用 graphiql 等),将其保存到项目中的 .graphql 文件中。

  • 为了为响应提供精确的类型,graphql_client 需要在编译时读取查询和模式。

    下载模式有多种选择。该项目提供了一个 CLI,但使用什么工具无关紧要,生成的 schema.json 是相同的。

  • 我们现在拥有了为我们的查询推导 Rust 类型的所有必要信息。这通过一个过程宏实现,如下面的代码片段所示

    use graphql_client::GraphQLQuery;
    
    // The paths are relative to the directory where your `Cargo.toml` is located.
    // Both json and the GraphQL schema language are supported as sources for the schema
    #[derive(GraphQLQuery)]
    #[graphql(
        schema_path = "tests/unions/union_schema.graphql",
        query_path = "tests/unions/union_query.graphql",
    )]
    pub struct UnionQuery;
    

    例如,derive 将生成一个名为 union_query 的模块 - 名称是结构体的名称,但以蛇形命名。

    该模块包含所有必要的结构和枚举定义,以反序列化该查询的响应。

    响应的根类型被命名为 ResponseData。GraphQL 响应将采用以下形式 Response<ResponseData>Response 类型始终相同)。

    该模块还包含一个名为 Variables 的结构体,表示查询所需的变量。

  • 我们现在需要创建要发送到服务器的完整负载。为了方便,GraphQLQuery trait 已在 derive 结构体中实现,因此可以通过这种方式创建完整的查询体

    use graphql_client::{GraphQLQuery, Response};
    use std::error::Error;
    use reqwest;
    
    #[derive(GraphQLQuery)]
    #[graphql(
        schema_path = "tests/unions/union_schema.graphql",
        query_path = "tests/unions/union_query.graphql",
        response_derives = "Debug",
    )]
    pub struct UnionQuery;
    
    async fn perform_my_query(variables: union_query::Variables) -> Result<(), Box<dyn Error>> {
    
        // this is the important line
        let request_body = UnionQuery::build_query(variables);
    
        let client = reqwest::Client::new();
        let mut res = client.post("/graphql").json(&request_body).send().await?;
        let response_body: Response<union_query::ResponseData> = res.json().await?;
        println!("{:#?}", response_body);
        Ok(())
    }
    

GitHub GraphQL API 的完整示例可用.

使用 CLI 的替代工作流程

您可以使用命令行界面到库的库来内省 GraphQL API 并生成模块

$ cargo install graphql_client_cli
$ graphql-client --help

在响应上派生特定特性

生成的响应类型始终派生自 serde::Deserialize,但您可能想要打印它们(Debug),比较它们(PartialEq)或派生其上的任何其他特性。您可以通过 response_derives 选项实现此功能 graphql 特性。例如

use graphql_client::GraphQLQuery;

#[derive(GraphQLQuery)]
#[graphql(
    schema_path = "tests/unions/union_schema.graphql",
    query_path = "tests/unions/union_query.graphql",
    response_derives = "Serialize,PartialEq",
)]
struct UnionQuery;

隐式空值

生成的代码将跳过 None 值的序列化。

use graphql_client::GraphQLQuery;

#[derive(GraphQLQuery)]
#[graphql(
    schema_path = "tests/unions/union_schema.graphql",
    query_path = "tests/unions/union_query.graphql",
    skip_serializing_none
)]
struct UnionQuery;

自定义标量

在 GraphQL 中,有五种标量类型 IntFloatStringBooleanID 可用,并且自动映射到 Rust 中的等效类型。但是,服务提供商还可以通过将声明如 scalar URI 添加到服务器模式来定义自定义标量类型。

如果在该模式中定义了此类自定义标量类型,则生成的代码将根据查询的内容引用这些标量类型。这意味着您必须在 derive 结构体的作用域内提供匹配的 Rust 类型。它可以像声明 type URI = String; 一样简单。这使您能够完全自由地处理自定义标量,只要它们可以被反序列化。如果没有提供此类声明,您将得到类似这样的构建错误

error[E0412]: cannot find type `URI` in module `super`
   |
   | #[derive(GraphQLQuery)]
   |          ^^^^^^^^^^^^ not found in `super`
   |
   = note: possible candidate is found in another module, you can import it into scope:
           crate::repo_view::URI

弃用

生成的代码支持 @deprecated 字段注解。您可以通过 GraphQLQuery derive 中的 deprecated 参数配置如何处理弃用

use graphql_client::GraphQLQuery;

#[derive(GraphQLQuery)]
#[graphql(
  schema_path = "tests/unions/union_schema.graphql",
  query_path = "tests/unions/union_query.graphql",
  deprecated = "warn"
)]
pub struct UnionQuery;

有效的值是

  • allow:响应结构体字段不被标记为弃用。
  • warn:响应结构体字段被标记为 #[deprecated]
  • deny:结构体字段不包括在响应结构体中,使用它们会导致编译错误。

默认值为 warn

具有多个操作的查询文档

您可以在一个查询文档(一个 .graphql 文件)中编写多个操作。然后,您可以通过将具有与操作之一相同名称的结构体命名为 #[derive(GraphQLQuery)] 来选择其中一个。这样很方便,因为它允许操作之间共享片段。

请注意,GraphQL文件中的结构和操作 必须 有相同的名称。我们强制执行此要求以使生成的代码更可预测。

use graphql_client::GraphQLQuery;

#[derive(GraphQLQuery)]
#[graphql(
    schema_path = "tests/unions/union_schema.graphql",
    query_path = "tests/unions/union_query.graphql",
)]
pub struct UnionQuery;

有关示例,请参阅 测试中的示例

生成模块的文档

您可以使用 cargo doc --document-private-items 在生成的代码上生成rustdoc文档。

当 .graphql 文件更改时使 cargo 重新编译

您可以在您的 Cargo.toml 中添加一个 include 选项。然而,目前它存在一些问题(见 此问题)。

示例

请参阅此存储库中的 示例目录

贡献者

对所有以任何方式(不仅仅是代码)为此项目做出贡献的人表示衷心的感谢

  • Alex Vlasov (@indifferentalex)
  • Ben Boeckel (@mathstuf)
  • Chris Fung (@aergonaut)
  • Christian Legnitto (@LegNeato)
  • David Gräff (@davidgraeff)
  • Dirkjan Ochtman (@djc)
  • Fausto Nunez Alberro (@brainlessdeveloper)
  • Hirokazu Hata (@h-michael)
  • Peter Gundel (@peterfication)
  • Sonny Scroggin (@scrogson)
  • Sooraj Chandran (@SoorajChandran)
  • Tom Houlé (@tomhoule)

行为准则

任何与本项目互动的人,包括但不限于此GitHub仓库,都必须遵守我们的 行为准则

许可证

许可方式如下

贡献

除非您明确表示,否则您有意提交以包含在本作品中(根据Apache-2.0许可证定义),则应按上述方式双许可,而无需任何额外条款或条件。

依赖项

~2–15MB
~226K SLoC